Make a class non-copyable *and* non-movable

2020-06-01 07:18发布

问题:

Before C++11, I could use this to make a class non-copyable:

private:
MyClass(const MyClass&);
MyClass& operator=(const MyClass&);

With C++11, I can do it like this instead:

MyClass(const MyClass&) = delete;
MyClass& operator=(const MyClass&) = delete;

When using the class with the deleted copy and assignment, is there a chance that a default move operator is generated? And the class is not exactly copied, but moved (which is sort of similar) after all?

So, do I have to do this to prevent default move construction and assignmnent:

MyClass(MyClass&&) = delete;
MyClass& operator=(MyClass&&) = delete;

... ?

回答1:

As others already mentioned in the comments, deleted constructors was introduced in C++11. To answer your question, the following rules hold in general:

  1. The two copy operations are independent. Declaring copy constructor does not prevent compiler to generate copy assignment and vice versa. (Same as in C++98)
  2. Move operations are not independent. Declaring either one of them prevents the compiler to generate the other. (Different from copy operations.)
  3. If any of the copy operations is declared, then none of the move operation will be generated. (Your case.)
  4. If any of the move operation is declared, then none of the copy operation will be generated. This is the opposite rule of the previous.
  5. If a destructor is declared, then none of the move operation will be generated. Copy operations are still generated for reverse compatibility with C++98.
  6. Default constructor generated only when no constructor is declared. (Same as in C++98)

As requested in the comments, here are some sources (C++11 is draft N3242):

  • Copy operations: § 12.8.8, § 12.8.19
  • Move operations: § 12.8.10, § 12.8.21
  • Default constructor: § 12.1.5


回答2:

Move constructor/assignment are not generated when you declare a copy constructor.

So

MyClass(MyClass&&) = delete;
MyClass& operator=(MyClass&&) = delete;

are not required.

You can still add it to be more explicit.