基本上,为什么这是有效的:
auto p1 = new int[10]{5};
但这不是:
auto p1 = new int[10](5);
更一般地说,新表达式初始化程序的规则是什么?
我发现了以下内容:
- 如果省略new-initializer,则默认初始化对象(8.5)。 [注意:如果未执行初始化,则对象具有不确定的值。 - 结束说明] - 否则,根据8.5的初始化规则解释new-initializer以进行直接初始化。
第二种情况也是如此,因为T((5))
之类的smth无效(从表达式(5)
直接初始化)?或者是什么原因?
编辑:好吧,我对(())
事情的建议似乎很愚蠢,因为我认为没有理由只应用于数组new-expression。
答案 0 :(得分:7)
第一个是有效的,因为list initialization(自C ++ 11以来),
new T { arg1, arg2, ... }
和
如果T是聚合类型,则执行聚合初始化。
int[10]
是属于聚合类型的数组类型,然后执行aggregate initialization,
如果初始化程序子句的数量少于成员数
and bases (since C++17)
或初始化程序列表完全为空,则其余成员and bases (since C++17)
将按空列表初始化by their default initializers, if provided in the class definition, and otherwise (since C++14)
,具体如下:通常的列表初始化规则(使用默认构造函数执行非类类型和非聚合类的值初始化,以及聚合的聚合初始化)。如果引用类型的成员是其余成员之一,则该程序格式不正确。
因此auto p1 = new int[10]{5};
将创建一个指向数组的指针,其第一个元素初始化为5
,其余元素初始化为0
。
第二个是direct initialization,因此new int[10](5);
表示直接从单个int[10]
int
初始化数组5
;这是无效的。
事实上,对于array new expression,您无法指定非空括号的初始值设定项。
如果type是数组类型,则初始化对象数组。
- 如果缺少初始化程序,则每个元素都是默认初始化的
- 如果初始化程序是一对空括号,则每个元素都是值初始化的。
- 如果初始化程序是括号括起来的参数列表,则数组是聚合初始化的。 (自C ++ 11起)
所以
auto p1 = new int[10]; // valid
auto p2 = new int[10](); // valid
auto p3 = new int[10]{5}; // valid
auto p4 = new int[10](5); // invalid
从标准的角度来看,正如您所引用的,[expr.new]/18:
创建类型为T的对象的new-expression初始化该表达式 对象如下:
- 如果省略new-initializer,则默认初始化对象([dcl.init])。 [注意:如果没有执行初始化,则为对象 具有不确定的价值。 - 尾注]
=>适用于auto p1 = new int[10];
,导致默认初始化。
- 否则,根据[dcl.init]的初始化规则解释new-initializer以进行直接初始化。
- (17.1)如果初始化程序是(非括号的)braced-init-list或is = braced-init-list,则对象或引用是列表初始化的。
=>适用于auto p3 = new int[10]{5};
,导致列表初始化,详细信息如上所述。
- (17.4)如果初始值设定项为(),则对象进行值初始化。
=>适用于auto p2 = new int[10]();
,会导致值初始化。
- (17.5)否则,如果目标类型是数组,则程序格式错误。
=>适用于auto p4 = new int[10](5);
。