由于int()
和int{}
是常量值等于0
的表达式,我认为它们是等价且可互换的,因此编译器必须平等对待它们。例如,
int a[0]; //error: zero-sized array not allowed in ISO C++
int b[int()]; //error: zero-sized array not allowed in ISO C++
int c[int{}]; //error: zero-sized array not allowed in ISO C++
但似乎有一些角落的情况,他们不可互换。
初始化指针时:
int *p = 0; //ok
int *q = int(); //error - by clang only
int *r = int{}; //error - by gcc and clang both
查看GCC和Clang条消息。我怀疑这是两个编译器中的错误,因为我希望它们在这种情况下可以互换,但我很高兴被证明是错误的。 : - )
传递给课程模板时:
template<int N> struct X{};
X<0> x1; //ok
X<int{}> x2; //ok (same as X<0>)
X<int()> x3; //error
我发现语法X<int()>
非常熟悉,就像我之前看到的(并且可能已经使用过)类似的语法,例如在std::function<int()>
中,模板参数int()
应该是函数类型(而不是0
)不带参数并返回int
。但我想知道规范的一部分,在此上下文中int()
将被视为函数 type ,并且不等同于int{}
,它总是{{1} }}
答案 0 :(得分:5)
表达式int()
和int{}
都是整数类型的常量表达式prvalues,它们的计算结果为零,因此可以在需要整数常量表达式的任何上下文中与文字0
互换整数类型的prvalue,其值为零。
两个表达式都满足 5.19 Constant Expressions [expr.const] 中指定的常量表达式的要求。
关于X<int()>
,该标准指定int()
在此上下文中不被解释为表达式:
14.3模板参数[temp.arg]
在 template-argument 中, type-id 和表达式之间的歧义被解析为 type-id ,无论相应的模板参数的形式如何。
关于指针转换:
4.10指针转换[conv.ptr]
空指针常量是整数类型的整数常量表达式(5.19)prvalue,其值为零 或
std::nullptr_t
类型的prvalue。
基于上面的段落,int()
和int{}
都是空指针常量表达式。这指向(非常小的)编译器错误,尽管有一个打开的缺陷报告(903)可能会导致此段发生变化:
CWG中有一个强烈的共识,即只有文字0应被视为空指针常量,而不是当前指定的任何零值常量表达式。
以下措辞涉及表达式int()
的价值:
8.5初始值设定项[dcl.init]
对T类型的对象或引用进行零初始化意味着:
[省略的不适用的条款]
- 如果T是标量类型(3.9),则将对象设置为值0(零),作为整数常量表达式, 转换为T
[...]
对T类型的对象进行值初始化意味着:
- 如果T是具有用户提供的构造函数(12.1)的(可能是cv限定的)类类型(第9节),那么 调用T的默认构造函数(如果T没有可访问的默认值,则初始化是错误的 构造函数);
[省略的不适用的条款]
- 否则,该对象为零初始化。
初始化程序为空括号的对象,即(),应进行值初始化。
int{}
的价值:
8.5.4列表初始化[dcl.init.list]
对象或类型T的引用的列表初始化定义如下:
- 如果初始化列表没有元素,而T是具有默认构造函数的类类型,则对象为 值初始化。
[省略的不适用的条款]
- 否则,如果初始化列表没有元素,则对象进行值初始化。
所有引自C ++工作草案标准N3337。