Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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;

... ?

like image 654
Jan Rüegg Avatar asked Oct 13 '15 07:10

Jan Rüegg


People also ask

How do I make my class non copyable?

class NonCopyable { public: NonCopyable (const NonCopyable &) = delete; NonCopyable & operator = (const NonCopyable &) = delete; protected: NonCopyable () = default; ~NonCopyable () = default; /// Protected non-virtual destructor }; class CantCopy : private NonCopyable {};

What is boost NonCopyable?

Boost::noncopyable prevents the classes methods from accidentally using the private copy constructor. Less code with boost::noncopyable.

How can we prevent copying or copy assigning any instance of a class?

There are three ways to prevent such an object copy: keeping the copy constructor and assignment operator private, using a special non-copyable mixin, or deleting those special member functions. A class that represents a wrapper stream of a file should not have its instance copied around.


2 Answers

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
like image 191
mcserep Avatar answered Oct 04 '22 07:10

mcserep


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.

like image 23
Jarod42 Avatar answered Oct 04 '22 07:10

Jarod42