Nó sẽ được rõ ràng rằng
struct text_descriptor td[3] = {
{0, {465,223}, 123},
{1, {465,262}, 123},
};
là danh sách-khởi động, và rằng danh sách initialiser là không có sản phẩm nào.
C++ 11 nói ([dcl.init.list] p3):
List-initialization of an object or reference of type T
is defined as follows:
- If the initializer list has no elements and
T
is a class type with a default constructor, the object is value-initialized.
- Otherwise, if
T
is an aggregate, aggregate initialization is performed (8.5.1).
- ...
[dcl.init.aggr] p1:
An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1), no brace-or-equal-initializers for non-static data members (9.2), no private or protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3).
td
là một mảng, vì vậy nó là một tổng hợp, do đó, tổng hợp initialisation được thực hiện.
[dcl.init.aggr] p7:
If there are fewer initializer-clauses in the list than there are members in the aggregate, then each member not explicitly initialized shall be initialized from an empty initializer list (8.5.4).
Đây là trường hợp ở đây, vì vậy td[2]
được khởi tạo từ một danh sách initialiser trống rỗng, mà ([dcl.init.list] p3 một lần nữa) có nghĩa là nó được khởi tạo giá trị.
giá trị khởi động, đến lượt nó, nghĩa là ([dcl.init] p7):
To value-initialize an object of type T
means:
- if
T
is a (possibly cv-qualified) class type (Clause 9) with a user-provided constructor (12.1), ...
- if
T
is a (possibly cv-qualified) non-union class type without a user-provided constructor, then the object is zero-initialized and, if T
's implicitly-declared default constructor is non-trivial, that constructor is called.
- ...
lớp học của bạn text_descriptor
là một lớp không có constructor dùng cung cấp, vì vậy td[2]
là lần đầu tiên zero-khởi tạo, và thì hàm tạo của nó được gọi.
phương tiện Zero-khởi động ([dcl.init] p5):
To zero-initialize an object or reference of type T means:
- if
T
is a scalar type (3.9), ...
- if
T
is a (possibly cv-qualified) non-union class type, each non-static data member and each base-class subobject is zero-initialized and padding is initialized to zero bits;
- if
T
is a (possibly cv-qualified) union type, ...
- if
T
is an array type, ...
- if
T
is a reference type, no initialization is performed.
này được xác định rõ bất kể constructor mặc định text_descriptor
's: nó chỉ zero-initialises các thành viên phi tham khảo và phụ các thành viên.
Sau đó, hàm tạo mặc định được gọi, nếu nó không nhỏ. Đây là cách các nhà xây dựng mặc định được định nghĩa ([đặc biệt] p5):
A default constructor for a class X
is a constructor of class X
that can be called without an argument. If there is no user-declared constructor for class X
, a constructor having no parameters is implicitly declared as defaulted (8.4). An implicitly-declared default constructor is an inline public member of its class. A defaulted default constructor for class X
is defined as deleted if:
- ...
- any non-static data member with no brace-or-equal-initializer is of reference type,
- ...
A default constructor is trivial if it is not user-provided and if:
- its class has no virtual functions (10.3) and no virtual base classes (10.1), and
- no non-static data member of its class has a brace-or-equal-initializer, and
- all the direct base classes of its class have trivial default constructors, and
- for all the non-static data members of its class that are of class type (or array thereof), each such class has a trivial default constructor.
Otherwise, the default constructor is non-trivial.
Vì vậy, các nhà xây dựng ngầm được xác định sẽ bị xóa, như mong đợi, nhưng nó cũng là tầm thường, nếu pos
là một loại POD (!) . Bởi vì hàm tạo là tầm thường, nó không được gọi. Bởi vì các nhà xây dựng không được gọi là, thực tế là nó bị xóa không phải là một vấn đề.
Đây là lỗ hổng trong C++ 11, đã được sửa. Nó đã xảy ra đã được cố định để đối phó với inaccessible trivial default constructors, nhưng từ ngữ cố định cũng bao gồm các nhà thầu mặc định tầm thường đã bị xóa. N4140 (khoảng C++ 14) nói trong [dcl.init.aggr] p7 (tôi nhấn mạnh):
- if
T
is a (possibly cv-qualified) class type without a user-provided or deleted default constructor, then the object is zero-initialized and the semantic constraints for default-initialization are checked, and if T
has a non-trivial default constructor, the object is default-initialized;
Như T.C. chỉ ra trong các ý kiến, another DR cũng thay đổi để td[2]
vẫn được khởi tạo từ một danh sách khởi tạo rỗng, nhưng danh sách initialiser trống bây giờ ngụ ý khởi tạo tổng hợp. Điều đó, đến lượt nó, ngụ ý rằng mỗi thành viên của td[2]
được khởi tạo từ một danh sách khởi tạo rỗng ([dcl.init.aggr] p7 một lần nữa), vì vậy dường như khởi tạo thành viên tham chiếu từ {}
.
[dcl.init.aggr] p9 sau đó nói (như remyabel đã chỉ ra trong một câu trả lời bây giờ bị xóa):
If an incomplete or empty initializer-list leaves a member of reference type uninitialized, the program is ill-formed.
Không rõ với tôi rằng điều này áp dụng đối với tài liệu tham khảo được khởi tạo từ ngầm {}
, nhưng các trình biên dịch giải thích nó như vậy, và không có nhiều thứ khác có thể có nghĩa là nó.
Phiên bản trình biên dịch là quan trọng. [Clang 3.5 và GCC 4.9.2] (http://coliru.stacked-crooked.com/a/4669040f8cc1bd3e) không biên dịch điều này. –
Trông giống như một lỗi trình biên dịch. Tôi có thể tái tạo trên GCC 4.8 và trước đó, vì vậy có vẻ như nó đã được sửa trong 4.9. –
MSVC 2013 cũng không biên dịch nó. – Drop