Wak*_*zil 9 c++ initialization language-lawyer c++11 c++14
对于聚合
struct S{int i, j;};
Run Code Online (Sandbox Code Playgroud)
根据N3797§8.5p16 声明S s({1, 2});和S s({1});执行直接初始化:
表单中发生的初始化
Run Code Online (Sandbox Code Playgroud)T x(a); T x{a};在
new表达式(5.3.4)中,static_cast表达式(5.2.9),函数表示法类型转换(5.2.3)以及基本和成员初始化器(12.6.2)称为直接初始化.
但§8.5p17似乎没有表征它们:
初始化器的语义如下.的目标类型是对象或引用的类型被初始化和源类型是初始化表达式的类型.如果初始化程序不是单个(可能带括号的)表达式,则不定义源类型.
如果初始化程序是(非括号的)braced-init-list,则对象或引用是列表初始化的(8.5.4).
如果目标类型是引用类型,请参见8.5.3.
如果目标类型是字符数组,数组
char16_t,数组char32_t或数组wchar_t,并且初始值设定项是字符串文字,请参见8.5.2.如果初始化程序是
(),则对象进行值初始化.否则,如果目标类型是数组,则程序格式错误.
如果目标类型是(可能是cv限定的)类类型:
如果初始化是直接初始化,或者它是复制初始化,其中源类型的cv-nonqualified版本与目标类相同的类或派生类,则考虑构造函数.列举了适用的构造函数(13.3.1.3),并通过重载解析(13.3)选择最佳构造函数.调用所选的构造函数来初始化对象,初始化表达式或表达式列表作为其参数.如果没有构造函数适用,或者重载决策是不明确的,则初始化是错误的.
否则(即,对于剩余的复制初始化情况),可以如13.3中所述枚举可以从源类型转换为目的地类型或(当使用转换函数时)到其派生类的用户定义的转换序列. 1.4,通过重载决策(13.3)选择最好的一个.如果转换不能完成或不明确,则初始化是错误的.选择的函数以初始化表达式作为参数调用; 如果函数是构造函数,则调用初始化目标类型的cv-nonqualified版本的临时函数.临时是一个prvalue.然后,根据上面的规则,调用的结果(对于构造函数的情况是临时的)用于直接初始化作为复制初始化目标的对象.在某些情况下,允许实现通过将中间结果直接构造到正在初始化的对象中来消除此直接初始化中固有的复制; 见12.2,12.8.
否则,如果源类型是(可能是cv限定的)类类型,则考虑转换函数.列举了适用的转换函数(13.3.1.5),并通过重载决策(13.3)选择最佳函数.调用如此选择的用户定义转换以将初始化表达式转换为正在初始化的对象.如果转换不能完成或不明确,则初始化是错误的.
否则,正在初始化的对象的初始值是初始化表达式的(可能已转换)值.如有必要,将使用标准转换(第4节)将初始化表达式转换为目标类型的cv非限定版本; 不考虑用户定义的转换.如果无法进行转换,则初始化不正确.[ 注:类型"的表达式CV1
T"可初始化类型"的对象CV2T"独立于cv修饰符的CV1和CV2.Run Code Online (Sandbox Code Playgroud)int a; const int b = a; int c = b;- 结束说明 ]
主题声明,S s({1, 2});和S s({1});:
()\n\n\n声明
\nS s({1, 2});和S s({1});根据 N3797 \xc2\xa78.5 p16 进行
嗯,是的,也不是。在第一种情况下,与第二种情况类似,Sx 值对象是用 构造的{1, 2},然后传递给隐式声明的复制构造函数s左值的隐式声明的复制构造函数。
\xc2\xa78.5 p16 正在讨论的情况并非如此,因为初始化不是采用以下形式:
\n\nS s(a);\nS s{a};\nRun Code Online (Sandbox Code Playgroud)\n\n除非标准认为a是什么。即便如此,它也不属于他在 ( new,static_cast,等等)
\n\n\n主题声明,
\nS s({1, 2});以及S s({1});不是列表初始化,因为每个初始化器都是带括号的花括号初始化列表。
表达式{1, 2}和{1}肯定是临时/过期对象的列表初始化S。