数组新表达式中的直接初始化与列表初始化
Direct-init vs. list-init in array new-expression
基本上,为什么这是有效的:
auto p1 = new int[10]{5};
但这不是:
auto p1 = new int[10](5);
更一般地说,new 表达式初始值设定项的规则是什么?
我发现了以下内容:
— If the new-initializer is omitted, the object is default-initialized (8.5). [ Note: If no initialization is performed, the object has an indeterminate value. — end note ]
— Otherwise, the new-initializer is interpreted according to the initialization rules of 8.5 for direct- initialization.
那么第二种情况是否无效,因为像T((5))
这样的东西是无效的(直接从表达式(5)
初始化)?或者是什么原因?
编辑:好吧,我对 (())
的建议似乎很愚蠢,因为我看不出为什么它只适用于数组 new 表达式。
第一个有效,因为 list initialization (C++11 起),
new T { arg1, arg2, ... }
和
If T is an aggregate type, aggregate initialization is performed.
int[10]
是数组类型,属于聚合类型,则执行aggregate initialization,
If the number of initializer clauses is less than the number of members and bases (since C++17)
or initializer list is completely empty, the remaining members and bases (since C++17)
are initialized by their default initializers, if provided in the class definition, and otherwise (since C++14)
by empty lists, in accordance with the usual list-initialization rules (which performs value-initialization for non-class types and non-aggregate classes with default constructors, and aggregate initialization for aggregates). If a member of a reference type is one of these remaining members, the program is ill-formed.
因此auto p1 = new int[10]{5};
会创建一个指向数组的指针,其第一个元素初始化为5
,其余元素初始化为0
。
第二个是direct initialization,所以new int[10](5);
表示直接从单个int
5
初始化数组int[10]
;这是无效的。
事实上,对于 array new expression 你不能指定 non-empty 带括号的初始值设定项。
If type is an array type, an array of objects is initialized.
- If initializer is absent, each element is default-initialized
- If initializer is an empty pair of parentheses, each element is value-initialized.
- If initializer is a brace-enclosed list of arguments, the array is aggregate-initialized. (since 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:
A new-expression that creates an object of type T initializes that
object as follows:
- If the new-initializer is omitted, the object is default-initialized ([dcl.init]). [ Note: If no initialization is performed, the object
has an indeterminate value. — end note ]
=> 申请 auto p1 = new int[10];
,导致 default-initialization。
- Otherwise, the new-initializer is interpreted according to the initialization rules of [dcl.init] for direct-initialization.
- (17.1) If the initializer is a (non-parenthesized) braced-init-list or is = braced-init-list, the object or reference is list-initialized.
=>申请auto p3 = new int[10]{5};
,导致列表初始化,上面有详细说明。
- (17.4) If the initializer is (), the object is value-initialized.
=> 申请 auto p2 = new int[10]();
,导致值初始化。
- (17.5) Otherwise, if the destination type is an array, the program is ill-formed.
=> 申请 auto p4 = new int[10](5);
.
基本上,为什么这是有效的:
auto p1 = new int[10]{5};
但这不是:
auto p1 = new int[10](5);
更一般地说,new 表达式初始值设定项的规则是什么?
我发现了以下内容:
— If the new-initializer is omitted, the object is default-initialized (8.5). [ Note: If no initialization is performed, the object has an indeterminate value. — end note ] — Otherwise, the new-initializer is interpreted according to the initialization rules of 8.5 for direct- initialization.
那么第二种情况是否无效,因为像T((5))
这样的东西是无效的(直接从表达式(5)
初始化)?或者是什么原因?
编辑:好吧,我对 (())
的建议似乎很愚蠢,因为我看不出为什么它只适用于数组 new 表达式。
第一个有效,因为 list initialization (C++11 起),
new T { arg1, arg2, ... }
和
If T is an aggregate type, aggregate initialization is performed.
int[10]
是数组类型,属于聚合类型,则执行aggregate initialization,
If the number of initializer clauses is less than the number of members
and bases (since C++17)
or initializer list is completely empty, the remaining membersand bases (since C++17)
are initializedby their default initializers, if provided in the class definition, and otherwise (since C++14)
by empty lists, in accordance with the usual list-initialization rules (which performs value-initialization for non-class types and non-aggregate classes with default constructors, and aggregate initialization for aggregates). If a member of a reference type is one of these remaining members, the program is ill-formed.
因此auto p1 = new int[10]{5};
会创建一个指向数组的指针,其第一个元素初始化为5
,其余元素初始化为0
。
第二个是direct initialization,所以new int[10](5);
表示直接从单个int
5
初始化数组int[10]
;这是无效的。
事实上,对于 array new expression 你不能指定 non-empty 带括号的初始值设定项。
If type is an array type, an array of objects is initialized.
- If initializer is absent, each element is default-initialized
- If initializer is an empty pair of parentheses, each element is value-initialized.
- If initializer is a brace-enclosed list of arguments, the array is aggregate-initialized. (since 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:
A new-expression that creates an object of type T initializes that object as follows:
- If the new-initializer is omitted, the object is default-initialized ([dcl.init]). [ Note: If no initialization is performed, the object has an indeterminate value. — end note ]
=> 申请 auto p1 = new int[10];
,导致 default-initialization。
- Otherwise, the new-initializer is interpreted according to the initialization rules of [dcl.init] for direct-initialization.
- (17.1) If the initializer is a (non-parenthesized) braced-init-list or is = braced-init-list, the object or reference is list-initialized.
=>申请auto p3 = new int[10]{5};
,导致列表初始化,上面有详细说明。
- (17.4) If the initializer is (), the object is value-initialized.
=> 申请 auto p2 = new int[10]();
,导致值初始化。
- (17.5) Otherwise, if the destination type is an array, the program is ill-formed.
=> 申请 auto p4 = new int[10](5);
.