QnA
QnA

Reputation: 1103

C++ move constructor, delete vs omission, when user defines copy ctor?

I have some simple questions regarding C++ move constructor, but so far didn't find a post that explains specifically what I saw below...

#include <utility>

class A
{
public:
    A() {}
    A(const A &) { std::cout << "copy Ctor" << std::endl; }
    A(A&&) { std::cout << "move Ctor" << std::endl; }
};

int main()
{
    A a;
    A b(std::move(a));
}

The output is

move Ctor

If I explicitly delete the move constructor,

    // A(A&&) { std::cout << "move Ctor" << std::endl; }
    A(A&&) = delete;

I got compilation error,

error: use of deleted function ‘A::A(const A&&)’

so far so good.

Then I read that move constructor is not auto-generated when there is user-defined copy ctors, and I thought instead of explicit deletion, 'not declare it' should give the same result,

    // A(A&&) { std::cout << "move Ctor" << std::endl; }
    // A(A&&) = delete;

but then I got this output,

copy Ctor

Now I am confused,

  1. When I omit the declaration of move ctor, does A b(std::move(a)) calls copy ctor directly? Is that part of the C++ standard? For regular functions this seems true - when a function's parameter is a xvalue, the function taking rvalue reference is preferred, and fallback is the function taking const lvalue reference.
  2. But, if 'move constructor is not auto-generated when there is user-defined copy ctors', why 'explicit deletion' vs 'not declaring' makes a difference?

Upvotes: 0

Views: 129

Answers (1)

Phil1970
Phil1970

Reputation: 2623

To make it somewhat easier to understand, I will use a somewhat unrelated example where the intended behavior might be a bit clearer.

Not much different that deleting a regular function:

struct A
{
    void f(int i) {}
    void f(double d) = delete;
};

A a;
a.f(1.1); // Error

If we comment out the second overload instead, then the first one will be used.

And it is quite obvious that it is an intended behavior as the purpose of deleting a function is to ensure that it is not called (if it is a better match than another overload).

Thus in my example above, one can easily prevent some undesirable conversions to happen.

Thyis is not much different than making a function private when public access is required. Deleting a function have the added benefit that it cannot be used from inside class member function. The other benefit is that the error happen at compile time instead of link time.

Upvotes: 1

Related Questions