Confused about c++ constructor deletion

94 Views Asked by At

This is my class

class A {
public:
    A(int);
    A(A const&) = delete;
    A& operator=(const A& a) = delete;
// etc.
};

In another file I can call the constructor like this:

auto foo = A(123);

That resolves to the copy constructor and not the one I expect, why?

error C2280: 'mynamspace::A::A(const mynamespace::A &)': attempting to reference a deleted function
1

There are 1 best solutions below

0
On

auto foo = A(123); performs copy initialization, in concept, A(123) constructs a temporary A by A::A(int) firstly, then foo is copy-initialized from the temporary by the copy constructor (PS A doesn't have move constructor). Before C++17 the code is ill-formed because the copy constructor is marked as delete.

Since C++17 the copy construction is elided completely because of mandatory copy elision and the code is well-formed.

(Since C++17) First, if T is a class type and the initializer is a prvalue expression whose cv-unqualified type is the same class as T, the initializer expression itself, rather than a temporary materialized from it, is used to initialize the destination object: see copy elision

and

(emphais mine)

(Since C++17) Under the following circumstances, the compilers are required to omit the copy and move construction of class objects, even if the copy/move constructor and the destructor have observable side-effects. The objects are constructed directly into the storage where they would otherwise be copied/moved to. The copy/move constructors need not be present or accessible:

Note that before C++17, copy elision is an optimization, even it might be performed the copy/move constructor still must be present and accessible.

This is an optimization: even when it takes place and the copy/move (since C++11) constructor is not called, it still must be present and accessible (as if no optimization happened at all), otherwise the program is ill-formed:

You can upgrade your compiler to support C++17, or use direct initialization (to remove the requirement of usage of copy constructor).

A foo(123);
A foo{123};