(类型)值和类型(值)有啥区别?

Posted

技术标签:

【中文标题】(类型)值和类型(值)有啥区别?【英文标题】:What is the difference between (type)value and type(value)?(类型)值和类型(值)有什么区别? 【发布时间】:2010-12-11 18:20:27 【问题描述】:

有什么区别

(type)value

type(value)

在 C++ 中?

【问题讨论】:

尚未提及的东西:(type)value;type(value); 是不同的——后者定义了一个名为 value 的变量。 【参考方案1】:

没有区别;根据标准(§5.2.3):

一个简单类型说明符(7.1.5)后跟一个带括号的表达式列表构造一个给定表达式列表的指定类型的值。如果表达式列表是单个表达式,则类型转换表达式等效于(在定义上,并且如果在含义上定义)对应的强制转换表达式(5.4)。

由于问题指定了type(value)(type)value之间的区别,所以绝对没有区别。

当且仅当您处理以逗号分隔的 list 值时,才会有区别。在这种情况下:

如果表达式列表指定了多个值,则类型应为具有适当声明的构造函数(8.5、12.1)的类,并且表达式 T(x1, x2, ...) 在效果上等同于声明 T t (x1, x2, ...);对于某些发明的临时变量 t,其结果是将 t 的值作为右值。

正如 Troubadour 所指出的,type(value) 版本根本无法编译某些类型的名称。例如:

char *a = (char *)string;

会编译,但是:

char *a = char *(string);

不会。但是,具有不同名称的相同类型(例如,使用 typedef 创建)可以工作:

typedef char *char_ptr;

char *a = char_ptr(string);

【讨论】:

嗯,没有没有区别。 +1 所以没有人愿意回答我关于类型类似于 char* 的问题。在第二种情况下它是语法错误的事实是可以的吗?哦,我猜 char* 并不属于所有类型。你每天都在这里学到新东西。 ;) @Troubadour,问题是关于type,而不是关于type*。它仍然适用于所有类型,因为制作合适的 typedef 将使 type 表示 char* @Troubadour,我现在明白你的意思了。但我说的是它适用于所有类型,而不仅仅是像你说的那样适用于“内置”。关键是char*identity<char*>::type(对于像boost::mpl::identity 这样的模板)和typetype 被定义为char* 时都表示相同的类型。这个问题的措辞是type 应该表示一个类型(显然)。 type 在语法上是一个简单类型说明符,但 char* 不是。这是一个type-id,您可以将其作为模板参数传递。另外,请不要侮辱别人,说他们写的是“废话”。 所以,说“有些类型的类型(值)版本根本不会编译[但其他版本会]”是错误的,因为它肯定会编译char* 表示的类型 - 如果你 typedef 或者你写成 identity<char*>::type(value)【参考方案2】:

没有区别; C++ 标准(1998 和 2003 版)对这一点很清楚。试试下面的程序,确保你使用的是兼容的编译器,比如http://comeaucomputing.com/tryitout/的免费预览版。

#include <cstdlib>
#include <string>
int main() 
  int('A'); (int) 'A'; // obvious
  (std::string) "abc"; // not so obvious
  unsigned(a_var) = 3; // see note below
  (long const&) a_var; // const or refs, which T(v) can't do
  return EXIT_SUCCESS;

注意:unsigned(a_var) 是不同的,但确实显示了这些确切标记可能意味着其他东西的一种方式。它声明了一个名为a_var 的无符号类型的变量,并且根本不是强制转换。 (如果您熟悉指向函数或数组的指针,请考虑如何在 p 周围使用括号,类型为 void (*pf)()int (*pa)[42]。)

(产生警告是因为这些语句不使用该值,并且在实际程序中这几乎可以肯定是一个错误,但一切仍然有效。我只是不忍心在完成所有内容后更改它上。)

【讨论】:

@squelart:一开始没有,但一旦接近了,我就开始工作了,只是不想为了摆脱警告而改变它。【参考方案3】:

两者都是强制类型转换时没有区别,但有时 'type(value)' 不是强制类型转换。

这是标准草案 N3242 第 8.2.1 节中的一个示例:

struct S 

    S(int);
;

void foo(double a) 

    S w( int(a) ); // function declaration
    S y( (int)a ); // object declaration

在这种情况下,'int(a)' 不是强制转换,因为 'a' 不是一个值,它是一个被冗余括号括起来的参数名称。文件指出

由函数样式之间的相似性引起的歧义 cast 和 6.8 中提到的声明也可以出现在上下文中 的声明。在这种情况下,选择是在一个函数之间 在参数周围带有一组冗余括号的声明 名称和具有函数样式转换的对象声明作为 初始化器。正如 6.8 中提到的歧义一样, 决议是考虑任何可能是 声明一个声明。

【讨论】:

【参考方案4】:

在 c 中没有 type (value),而在 c/c++ 中,type (value)(type) value 都是允许的。

【讨论】:

【参考方案5】:

为了说明你在 C++ 中的选择(只有一个有安全检查)

#include<boost/numeric/conversion/cast.hpp> 

using std::cout;
using std::endl;
int main()

    float smallf = 100.1;

    cout << (int)smallf << endl; // outputs 100 // c cast
    cout << int(smallf) << endl; // outputs 100 // c++ constructor = c cast

    cout << static_cast<int>(smallf) << endl; // outputs 100
//  cout << static_cast<int&>(smallf) << endl; // not allowed
    cout << reinterpret_cast<int&>(smallf) << endl; // outputs 1120416563
    cout << boost::numeric_cast<int>(smallf) << endl; // outputs 100

    float bigf = 1.23e12;

    cout << (int)bigf << endl; // outputs -2147483648
    cout << int(bigf) << endl; // outputs -2147483648

    cout << static_cast<int>(bigf) << endl; // outputs -2147483648
//  cout << static_cast<int&>(bigf) << endl; // not allowed
    cout << reinterpret_cast<int&>(bigf) << endl; // outputs 1401893083
    cout << boost::numeric_cast<int>(bigf) << endl; // throws bad numeric conversion

【讨论】:

以上是关于(类型)值和类型(值)有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

javascript原始值和引用值类型及区别

Go语言的断言返回值和类型转换的区别

c#中的引用类型和值类型有啥区别?

在 schema 中, simpleType 与 complexType有啥区别?

值类型和引用类的区别是啥?

.NET 中的结构和类有啥区别?