基本上,为什么有效:
auto p1 = new int[10]{5};
但不是:
auto p1 = new int[10](5);
以及更一般而言的新表达初始化器的规则是什么?
我找到了以下内容:
- 如果省略了新的initializer,则该对象被默认为initialized(8.5(。[注意:如果没有执行初始化,则对象具有不确定的值。 - 终点] - 否则,根据直接初始化的8.5的初始化规则来解释新的启动器。
因此,第二种情况是无效的,因为像 T((5))
这样的smth无效(来自表达式(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
5
初始化数组int[10]
;这是无效的。
实际上,对于阵列新表达式,您无法指定非空括号初始化器。
如果类型是数组类型,则初始化了一个对象数组。
- 如果不存在初始化器,则每个元素均为默认initialized
- 如果初始化器是一对空括号,则每个元素都是价值限制的。
- 如果初始化器是一个固定的参数列表,则该数组是汇总的。(由于C 11(
so
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初始化对象的新表达 对象如下:
- 如果省略了新的initializer,则该对象将被默认为initialized([dcl.init](。[注意:如果未执行初始化,则该对象 具有不确定的值。 - 终结注]
=>适用于auto p1 = new int[10];
,导致默认限制。
- 否则,根据[DCL.Init]的初始化规则来解释新的启动器。
和[dcl.init]/17:
- (17.1(如果初始化器是(未父母(支撑列表或IS = braced-Init-list,则对象或参考是列表initialized。
=>适用于auto p3 = new int[10]{5};
,导致列表初始化,详细信息在上面说明。
- (17.4(如果初始化器为((,则对象为价值。
=>适用于auto p2 = new int[10]();
,导致价值初始化。
- (17.5(否则,如果目标类型是数组,则该程序是不形成的。
=>适用于auto p4 = new int[10](5);
。