Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Could a class type with deleted default constructor be default initialized?

From what cppref says about value initialization

if T is a class type with no default constructor or with a user-provided or deleted default constructor, the object is default-initialized;

But since that class type has deleted default constructor, how could the object be default-initialized?

As far as I know, default initialization of class type needs the access of default constructor. If we have:

struct A {
    A() = delete;
    int k;
};

Then A *a = new A; will fail, so does A* a = new A();.

But A a{}; is OK. But why? According to cppreference

Otherwise, If the braced-init-list is empty and T is a class type with a default constructor, value-initialization is performed.

like image 782
scottxiao Avatar asked May 17 '18 14:05

scottxiao


People also ask

Can default constructor be deleted?

If no user-defined constructors are present and the implicitly-declared default constructor is not trivial, the user may still inhibit the automatic generation of an implicitly-defined default constructor by the compiler with the keyword delete.

Is default constructor always created?

No, the C++ compiler doesn't create a default constructor when we initialize our own, the compiler by default creates a default constructor for every class; But, if we define our own constructor, the compiler doesn't create the default constructor.

Can a class have no default constructor?

No default constructor is created for a class that has any constant or reference type members. A constructor of a class A is trivial if all the following are true: It is implicitly defined. A has no virtual functions and no virtual base classes.

What is default constructor and when the class has a default constructor?

A default constructor is a constructor that either has no parameters, or if it has parameters, all the parameters have default values. If no user-defined constructor exists for a class A and one is needed, the compiler implicitly declares a default parameterless constructor A::A() .


2 Answers

I think the standard just means "if T is a class type with deleted default constructor then goto default initialization". It would fail at last because the constructor selected for default initialization is deleted. It's used to distinguish with the 2nd case, i.e. "if T is a class type with a default constructor that is neither user-provided nor deleted", for that case zero-initialization is performed firstly, then default-initialization if T has a non-trivial default constructor.

A a{} is OK,but why?

Because when A is an aggregate type aggregate initialization is performed. Note that explicitly deleted constructors are allowed for aggregate type since C++11.

In all cases, if the empty pair of braces {} is used and T is an aggregate type, aggregate-initialization is performed instead of value-initialization.

And

An aggregate is one of the following types:

  • ...
  • class type (typically, struct or union), that has
    • ...
    • no user-provided, inherited, or explicit constructors (explicitly defaulted or deleted constructors are allowed) (since C++17) (until C++20)
    • ...

EDIT

Since C++20 the behavior changed; A a{}; would fail.

An aggregate is one of the following types:

  • ...
  • class type (typically, struct or union), that has
    • ...
    • no user-declared or inherited constructors (since C++20)
    • ...

A is not an aggregate again. A a{}; performs value-initialization (default-initialization), the deleted constructor is used and fails.

like image 74
songyuanyao Avatar answered Oct 07 '22 00:10

songyuanyao


But since that class type has deleted default constructor, how could the object be default-initialized?

Stating that the object is default-initialized doesn't in of itself imply that default-initialization is a valid thing to do. The wording just forwards us into that process, it makes the initialization process coherent, it doesn't imply that it must succeed.

For instance:

struct A {
    A() = delete;
    A(int); // not an aggregate
};

auto a = A(); 

The initializer is (), so this the object is value-initialized. In this case, that means it's default-initialized, which means we find a constructor.

Calling that constructor happens to be ill-formed, because it's deleted, which makes the whole initialization ill-formed. But we get to that point by way of default-initialization.

like image 45
Barry Avatar answered Oct 07 '22 00:10

Barry