led*_*ter 7 c++ initializer language-lawyer c++14 new-expression
基本上,为什么这是有效的:
auto p1 = new int[10]{5};
但这不是:
auto p1 = new int[10](5);
更一般地说,new-expression初始化程序的规则是什么?
我找到了以下内容:
- 如果省略new-initializer,则默认初始化对象(8.5).[注意:如果未执行初始化,则对象具有不确定的值. - 结束注释] - 否则,根据8.5的初始化规则解释new-initializer以进行直接初始化.
那么第二种情况是无效的,因为smth就像T((5))
是无效的(从表达式直接初始化(5)
)?或者是什么原因?
编辑:好吧,我对(())
事物的建议似乎很愚蠢,因为我认为没有理由为什么只应用于数组new-expression.
第一个是有效的,因为列表初始化(从C++ 11开始),
new T { arg1, arg2, ... }
和
如果T是聚合类型,则执行聚合初始化.
int[10]
是一个属于聚合类型的数组类型,然后执行聚合初始化,
如果初始化条款的数目小于成员的数量
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
.
第二个是直接初始化,所以new int[10](5);
意味着直接int[10]
从一个单元初始化数组int
5
; 这是无效的.
实际上,对于数组new表达式,您不能指定非空括号初始值设定项.
如果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
Run Code Online (Sandbox Code Playgroud)
从标准的角度来看,正如你所引用的,[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);
.