Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Most concise way to disable copying class in C++11

I have a problem dealing with deprecated since C++11 default generation of copy constructor and copy assignment operator when there is a user-defined destructor.

For most sufficiently simple classes default-generated constructors, operators and destructor are fine. Consider the following reasons to declare destructor:

  1. Making trivial destructor virtual in base class:

    // header
    class Base1 { public: virtual ~Base1() = default; };
    class Base2 { public: virtual ~Base2(); };
    // source
    Base2::~Base2() = default;
    

    Would all 4 copy and move special methods be generated by compiler in these cases? If yes, then I think it is fine and there is no need to complicate Base1 or Base2.

  2. Printing debug message in destructor:

    // header
    class D { public: ~D(); };
    // source
    D::~D() {
    #ifdef DEBUG_THIS
        std::cout << "D was destructed." << std::endl;
    #endif
    }
    

    I believe that in this case copy constructor and assignment operator would be generated; but move constructor and assignment operator would not. I want to avoid using deprecated default-generating and disable copying of D. I also want to avoid flooding D with 4 deleted declarations. Is disabling only one copy constructor enough? Is it a good style?

like image 210
vedg Avatar asked May 17 '14 09:05

vedg


People also ask

How can you prevent a class from being copied?

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.

How do I turn off move constructor?

To correct this, remove the move constructor completely. In the case of the class, once a copy constructor is present (user defined), the move is implicitly not generated anyway (move constructor and move assignment operator).

What is delete copy constructor?

The copy constructor and copy-assignment operator are public but deleted. It is a compile-time error to define or call a deleted function. The intent is clear to anyone who understands =default and =delete . You don't have to understand the rules for automatic generation of special member functions.

What is C++ move semantics?

Move semantics allows you to avoid unnecessary copies when working with temporary objects that are about to evaporate, and whose resources can safely be taken from that temporary object and used by another.


2 Answers

With C++11, a clean way is to follow the pattern used in boost (see here)

You basically create a base class where copy constructor and copy assignment are deleted, and inherit it:

class non_copyable
{
protected:
    non_copyable() = default;
    ~non_copyable() = default;

    non_copyable(non_copyable const &) = delete;
    void operator=(non_copyable const &x) = delete;
};

class MyClass: public non_copyable
{
...
}
like image 78
quantdev Avatar answered Sep 28 '22 05:09

quantdev


Deleting the copy-constructor and copy-assignment operator is the simplest and clearest way to disable copying:

class X
{
    X(X const &) = delete;
    void operator=(X const &x) = delete;
};

I don't follow what you are talking about with virtual destructors in the question body . It sounds like you're asking for a way to make your code take up fewer characters of source code, but also be more cryptic to anybody looking at it.

If the list of deleted functions bothers you, you could hide them behind a macro, I guess.

 #define NON_COPYABLE_NOR_MOVABLE(T) \ 
      T(T const &) = delete; \
      void operator=(T const &t) = delete; \
      T(T &&) = delete;
like image 20
M.M Avatar answered Sep 28 '22 04:09

M.M