了解对象初始化

6 c++ initialization

我在初始化数组时忘了写大括号:

struct A
{
    A() { std::cout << "A()" << std::endl; }
    A(int a) { std::cout << "A(" << a << ")" << std::endl; }
};

int main()
{
    A a[3] =  A(2), A(3);
}
Run Code Online (Sandbox Code Playgroud)

DEMO

输出:

A(2)
A(2)
A(2)
A(3)
Run Code Online (Sandbox Code Playgroud)

就我而言,这是正确的.N4257::12.6.1/2:

对于任何聚合,可以在初始化列表中省略大括号,即使聚合具有具有用户定义类型转换的类类型的成员也是如此

但支持初始化具有不同的副作用:

struct A
{
    A() { std::cout << "A()" << std::endl; }
    A(int a) { std::cout << "A(" << a << ")" << std::endl; }
};

int main()
{
    A a[3] = { A(2), A(3) };
}
Run Code Online (Sandbox Code Playgroud)

DEMO

输出:

A(2)
A(3)
A()
Run Code Online (Sandbox Code Playgroud)

你不能解释这个区别吗?

cpp*_*ner 4

N4527 \xc2\xa7 8.5 [dcl.init]

\n\n
\n

17 初始化器的语义如下。目标类型是正在初始化的对象或引用的类型,源类型是初始化表达式的类型。如果初始值设定项不是单个(可能\n 带括号的)表达式,则源类型不会被 de\xef\xac\x81ned。

\n\n

\xe2\x80\x94 (17.1) 如果初始化器是一个(非括号的)大括号初始化列表,则对象或引用是列表初始化的 (8.5.4)。

\n\n

\xe2\x80\x94 (17.2) 如果目标类型是引用类型,请参见 8.5.3。

\n\n

\xe2\x80\x94 (17.3) 如果目标类型是字符数组、char16_t 数组、char32_t 数组或\n wchar_t 数组,并且初始值设定项是字符串文字,请参阅 8.5.2。

\n\n

\xe2\x80\x94 (17.4) 如果初始化器是 (),则对象是值初始化的。

\n\n

\xe2\x80\x94 (17.5) 否则,如果目标类型是数组,则程序格式错误。

\n\n

[其他无关项目省略]

\n
\n\n

A a[3] = A(2)落入(17.5),所以你的程序是错误的。显然g++ 在这种情况下有一个错误clang 正确地拒绝了您的代码

\n