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

时间:2018-04-05 03:24:53

标签: c++ c++14 language-lawyer initializer new-expression

基本上,为什么这是有效的:

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。

1 个答案:

答案 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以进行直接初始化。
  •   

[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);