c++ - 0、int() 和 int{} 之间有什么区别?

标签 c++ gcc clang zero compile-time-constant

作为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
    

    参见 GCCClang消息。我怀疑这是两个编译器中的错误,因为我希望它们在这种情况下可以互换,但我很高兴被证明是错误的。 :-)

  • 传递给类模板时:

    template<int N> struct X{};
    
    X<0>      x1; //ok
    X<int{}>  x2; //ok (same as X<0>)
    X<int()>  x3; //error  
    

    参见 GCCClang消息。

    我找到语法 X<int()>非常熟悉,因为我以前见过(并且可能使用过)类似的语法,例如 std::function<int()> , 模板参数 int()预计是函数类型(而不是 0 )不带参数并返回 int .但我想知道规范中的这一部分 int()被视为函数 type 并且不等同于 int{}这总是 0 .

最佳答案

表达式 int()int{}都是计算结果为零的整数类型的常量表达式纯右值,因此可以与文字 0 互换。在需要计算结果为零的整数类型的整型常量表达式纯右值的任何上下文中。

这两个表达式都满足 5.19 常量表达式 [expr.const] 中指定的常量表达式的要求。

关于 X<int()> ,标准规定 int()在这种情况下不被解释为表达式:

14.3 Template arguments [temp.arg]

In a template-argument, an ambiguity between a type-id and an expression is resolved to a type-id, regardless of the form of the corresponding template-parameter.

关于指针转换:

4.10 Pointer conversions [conv.ptr]

A null pointer constant is an integral constant expression (5.19) prvalue of integer type that evaluates to zero or a prvalue of type std::nullptr_t.

根据以上段落,int()int{}是空指针常量表达式。这指向一个(非常小的)编译器错误,尽管有一个开放的缺陷报告(903)可能会导致本段更改:

There was a strong consensus among the CWG that only the literal 0 should be considered a null pointer constant, not any arbitrary zero-valued constant expression as is currently specified.

以下措辞处理表达式 int() 的值:

8.5 Initializers [dcl.init]

To zero-initialize an object or reference of type T means:

[omitted clauses which don't apply]

if T is a scalar type (3.9), the object is set to the value 0 (zero), taken as an integral constant expression, converted to T

[...]

To value-initialize an object of type T means:

— if T is a (possibly cv-qualified) class type (Clause 9) with a user-provided constructor (12.1), then the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);

[omitted clauses which don't apply]

otherwise, the object is zero-initialized.

An object whose initializer is an empty set of parentheses, i.e., (), shall be value-initialized.

而对于int{}的值(value):

8.5.4 List-initialization [dcl.init.list]

List-initialization of an object or reference of type T is defined as follows:

— If the initializer list has no elements and T is a class type with a default constructor, the object is value-initialized.

[omitted clauses which don't apply]

Otherwise, if the initializer list has no elements, the object is value-initialized.

所有引用自 C++ 工作草案标准 N3337。

关于c++ - 0、int() 和 int{} 之间有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19121890/

相关文章:

c - Windows 和 UTF-8 字符上的 MinGW + GCC

c++ - CMake 与 cygwin "make[2]: *** No rule to make target ' cygwin'“

ios - 警告 : Format string is not a string literal

c++ - (linux)Socket 返回 0

c++ - 用什么替换巨大的 switch 语句?

c - C工程编译的时候怎么最后没有创建main.o?

vim - Clang插件问题

c - 如何在 C 中获取源文件的完整路径?

c++ - 如何将 "Alt+space"热键绑定(bind)到 Qt 中的插槽?

c++ - 在 LuaSQL 代码上断言 C/C++