Last modified on 6 December 2012, at 19:40

More C++ Idioms/Non-copyable Mixin

Non-copyable MixinEdit

IntentEdit

To prevent objects of a class from being copy-constructed or assigned to each other.

Also Known AsEdit

MotivationEdit

Many times it makes sense to prevent copying of objects of a class. For example, a class that encapsulates network connections. Copying can't be meaningfully defined for such classes. So it should be explicitly prevented without relying on guidelines or discipline on the programmer's part. The intent should also be easily identifiable just by looking at the declaration of a class to improve readability.

Solution and Sample CodeEdit

A class called non-copyable is defined which has a private copy constructor and copy assignment operator.

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

CantCopy objects can't be copied because the copy constructor and copy assignment operators of the private base class NonCopyable are not accessible to the derived class. The traditional way to deal with these is to declare a private copy constructor and copy assignment, and then document why this is done. But deriving from noncopyable is simpler and clearer, and doesn't require additional documentation. private members of NonCopyable need not be defined. NonCopyable can also be categorized as a mixin-from-above because it defines a reusable module that "mixes-in" the feature of "non-copyability" into the derived class from "above". A CRTP based solution is given below. (This allows for Empty Base Optimization with multiple inheritance [see the Discussion page].)

template <class T>
class NonCopyable
{
  protected:
    NonCopyable () {}
    ~NonCopyable () {} /// Protected non-virtual destructor
  private: 
    NonCopyable (const NonCopyable &);
    NonCopyable & operator = (const NonCopyable &);
};
class CantCopy : private NonCopyable <CantCopy>
{};

Explicit copy-constructor

It is worthwhile to note that C++ allows one more way to control copy-construction. An explicit copy-constructor will prevent the compiler from calling a copy-constructor implicitly. I.e., passing an object by value and returning an object by value will be disabled for the class having an explicit copy-constructor. However, making explicit copies is allowed. On gcc, use --no-elide-constructors option to disable copy-elision. This option is useful to observe (actually not observe!) the effects of Return Value Optimization. It is generally not recommended to disable this important optimization.

struct NoImplicitCopy
{
  NoImplicitCopy () {}
  explicit NoImplicitCopy (const NoImplicitCopy &) {}
};
 
NoImplicitCopy foo()   // Compiler error because copy-constructor must be invoked implicitly to return by value.  
{
  NoImplicitCopy n;
  return n;
}
 
void bar(NoImplicitCopy n)   // Compiler error because copy-constructor must be invoked implicitly to pass by value.
{
}
 
int main(void)
{
  NoImplicitCopy n;
  NoImplicitCopy x(n);       // This is fine. explicit copy.
  n = foo();
  bar(n);
}

Known UsesEdit

boost::noncopyable

Related IdiomsEdit

Mixin-from-above

ReferencesEdit

  1. ISO/IEC 14882:2003 C++ Standard §12.8/4, §12.8/7