The more I read about C++11 uniform initialization, the more confused I am. Scott Meyers in Effective Modern C++ (page 55) says that the statement
Widget w2{};
always calls the default constructor (even in the presence of constructor with a std::initializer_list
argument).
At first sight, this seems to be consistent with the 4th edition of Stroustrup book "C++ programing language", e.g. according to the table on page 1200 the statement
std::atomic<T> x;
leaves the atomic variable uninitialized, while
std::atomic<T> x {};
calls "default constructor" so that x represents a value initialized T object.
However, I can't believe that std::atomic<T> x;
does not call the default constructor in C++11 anymore, so I'm totally confused here.
Finally, after taking a look at C++11 standard (n3337 draft) my confusion is even bigger. On page 1102 we have:
template <> struct atomic<integral > {
//[...] list of non-constructor functions
atomic() noexcept = default;
constexpr atomic(integral ) noexcept;
atomic(const atomic&) = delete;
//[...] other non-constructor functions
};
While on page 1104 (point 29.5.5) we see
The atomic integral specializations and the specialization atomic shall have standard layout. They shall each have a trivial default constructor and a trivial destructor. They shall each support aggregate initialization syntax.
So classes with user defined constructor now support aggregate initialization?
Is this so because the constuctor is constexpr
?
And what happens when we write
std::atomic<T> x {};
Is this the aggregate initialization? Or a call to the (trivial) default constructor?
Uniform initialization is a feature in C++ 11 that allows the usage of a consistent syntax to initialize variables and objects ranging from primitive type to aggregates. In other words, it introduces brace-initialization that uses braces ({}) to enclose initializer values.
Aggregate initialization is a form of list-initialization, which initializes aggregates. An aggregate is an object of the type that is one of the following. array type. class type (typically, struct or union), that has.
The uniform initialization is a feature that permits the usage of a consistent syntax to initialize variables and objects which are ranging from primitive type to aggregates. In other words, it introduces brace-initialization that applies braces ({}) to enclose initializer values.
If a type has a default constructor, either implicitly or explicitly declared, you can use brace initialization with empty braces to invoke it. For example, the following class may be initialized by using both empty and non-empty brace initialization: C++ Copy.
So classes with user defined constructor now support aggregate initialization?
Only aggregates support aggregate initialization. An aggregate can have a user defined constructor only if the constructor is defined as defaulted or deleted.
This will change in C++20 where no user declared constructors are allowed at all.
Is this so because the constuctor is consexpr?
constexpr
has no effect on this.
std::atomic<T> x {};
Is this the aggregate initialization?
This is list initialization. If the type is an aggregate, then list initialization would aggregate initialize the object. std::atomic
is not an aggregate, because it has a user-provided constructor that is neither defaulted nor deleted:
constexpr atomic( T desired ) noexcept; // (2) (since C++11)
For std::atomic
, this rule of list initialization applies:
- Otherwise, if the initializer list has no elements and T is a class type with a default constructor, the object is value-initialized.
And value initialization invokes the default constructor for such class.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With