数组new-expression中的Direct-init vs list-init

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.

son*_*yao 7

第一个是有效的,因为列表初始化(从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以进行直接初始化.

并且[dcl.init]/17:

  • (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);.