Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++14 value-initialization with deleted constructor

I have some misunderstanding:

Let's mark default constructor of struct A as deleted:

struct A {   A() = delete; }; 

The next instruction is well-formed and what's that effect?:

A a{}; 

From cppreference value initilization:

1) If T is a class type with no default constructor or with a user-provided default constructor or with a deleted default constructor, the object is default-initialized.

but then the effect of default initialization is:

If T is a class type, the default constructor is called to provide the initial value for the new object.

Or it's aggregate initialization? Thanks!

like image 619
Bikineev Avatar asked May 27 '14 06:05

Bikineev


People also ask

How do you initialize a value in C++?

The way to value-initialize a named variable before C++11 was T object = T();, which value-initializes a temporary and then copy-initializes the object: most compilers optimize out the copy in this case. References cannot be value-initialized.

Can default constructor be deleted?

The implicitly-declared or defaulted default constructor for class T is undefined (until C++11)defined as deleted (since C++11) if any of the following is true: T has a member of reference type without a brace-or-equal initializer.

How constructor solve the problem of initialization?

The constructors should be used to initialize member variables of the class because member variables cannot be declared or defined in a single statement. Therefore, constructors are used in initializing data members of a class when an object is created. Below is the C++ program to illustrate the above concept: C++

Can constructor return address of object being initialized?

The constructor only creates the object and never returns anything.


2 Answers

Your struct A is :

  • a class type that has:
    • no user-provided constructors1,
    • no private or protected non-static data members,
    • no base classes,
    • no virtual member functions.

It therefore qualifies as an aggregate type, according to the definition provided by § 8.5.1/1.

Then comes the priority of aggregate initialization over value initialization. The standard says that aggregate initialization has precedence over value intialization (draft N3936, § 8.5.4/3, page 201) (emphasis mine)

List-initialization of an object or reference of type T is defined as follows:

  • If T is an aggregate, aggregate initialization is performed (8.5.1).
  • Otherwise, if the initializer list has no elements and T is a class type with a default constructor, the object is value-initialized.
  • [... more rules...]

(1) As requested in the comments on why a deleted constructor does not count as user-defined, here is what the standard says (draft N3936, § 8.4.2/5, page 198):

A function is user-provided if it is user-declared and not explicitly defaulted or deleted on its first declaration.

like image 181
user703016 Avatar answered Sep 18 '22 04:09

user703016


It is well formed. A is an aggregate1, and, according to draft N3936, an empty initializer list used in direct-list initialization of an aggregate results in aggregate initialization:

From § 8.5.4/3 List-initialization [dcl.init.list]:

List-initialization of an object or reference of type T is defined as follows:

— If T is an aggregate, aggregate initialization is performed (8.5.1).

[ Example:

struct S2 { int m1; double m2, m3; };

....

S2 s23{}; // OK: default to 0,0,0

....

— end example ]

....

The relevant changes between C++11 and C++1y are a change in the precedence of aggregate vs. value initialization for the case of aggregates:

C++11 leads with

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)....

followed by the example above.

C++1y gives priority to aggregate initialization:

List-initialization of an object or reference of type T is defined as follows:

— If T is an aggregate, aggregate initialization is performed (8.5.1).

....

— Otherwise, if the initializer list has no elements and T is a class type with a default constructor, the object is value-initialized.


1 Why is A an aggregate?

It is an aggregate both in C++11 and C++14.

C++1y:

8.5.1 Aggregates [dcl.init.aggr]

An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1), no private or protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3).

The only part that is not obvious is whether the defaulted constructor is user-provided or not. It isn't:

In § 8.4.2 [dcl.fct.def.default]:

A function is user-provided if it is user-declared and not explicitly defaulted or deleted on its first declaration.

like image 27
juanchopanza Avatar answered Sep 20 '22 04:09

juanchopanza