C++ Initializer
昨天看到一行怪異程式碼:
char change[27] = {"abcdefghijklmnopqrstuvwxyz"};
直覺是不會過,但可得的編譯器全給過。於是翻閱 Holy Standard,最後在 Clause 8.5, par.13, p.146 找到:
If
T
is a scalar type, then a declaration of the formT x = { a };is equivalent to
T x = a;
其中 "scalar type" 的定義在 Clause 3.9, par.10, p.53:
Arithmetic types (3.9.1), enumeration types, pointer types, and pointer to member types (3.9.2), and cv-qualified versions of these types (3.9.3) are collectively called scalar types. Scalar types, POD-struct types, POD-union types (clause 9), arrays of such types and cv-qualified versions of these types (3.9.3) are collectively called POD types.
因此 array 並非 scalar types。不過邏輯上,標準書說的是「若『T
為 scalar type』,則『T x = { a };
等價於 T x = a;
』」,p => q 無法推得 ~p => ~q,因此效果上是保證 T
為 scalar type 時所發生的事,對於其它非 scalar type 的 T
,編譯器有權決定是否要實作那個等價關係。例如以下這句:
vector<int> v = {vector<int>()};
g++ 3.4.2 不給過,但 g++ 4.1.0 給過,應該是版本演進而放寬限制(又不違背標準)。至於 T
為 char[]
的情形(也就是一開始的問題),所有編譯器一致放行,或許是巧合,也可能是實作上較為方便,目前只能猜測。
另外,查閱標準途中,在 Clause 8.5, par.8, p.148 看到
An initializer for an aggregate member that is an empty class shall have the form of an empty
initializer-list
{}
. [Example:struct S { }; struct A { S s; int i; } a = { { } , 3 };—end example] An empty
initializer-list
can be used to initialize any aggregate. If the aggregate is not an empty class, then each member of the aggregate shall be initialized with a value of the formT()
(5.2.3), whereT
represents the type of the uninitialized member.
之後又花了不少時間,為了區分 zero-initialization、default-initialization、value-initialization,在標準書內展開兩萬五千里長征,晚一點補上。
--
律師真痛苦 XD。
<< 回到主頁