Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C++

C++ Tip: Make Your Class Non-copyable Without Boost

5.00/5 (6 votes)
10 Dec 2017CPOL 27.8K   48  
Make your class non-copyable without Boost

Image 1

Introduction

There are times where an object should never be passed by copy but by reference or pointer. For instance, the class has a data member (like counter or mutex) which should not be duplicated. In this tip, we take a look at 2 techniques which declare the class to be non-copyable without resorting to using Boost's Noncopyable class.

Use delete Keyword

Delete the copy constructor and assignment operator. This works for C++11 and above.

C++
// Works for C++11 and above
class DeletedCopyFunc
{
public:
    DeletedCopyFunc(int value): m_Value(value) {}
public:
    DeletedCopyFunc(const DeletedCopyFunc&) = delete;
    DeletedCopyFunc& operator=(const DeletedCopyFunc&) = delete;

private:
    int m_Value;
    std::mutex m_Mutex;
};

Make private

Declaring the copy constructor and assignment operator private is another way and it is perfectly fine not to define their bodies. This technique works for all C++ versions.

C++
// Works for all C++ versions
class PrivateCopyFunc
{
public:
    PrivateCopyFunc(int value) : m_Value(value) {}
private:
    PrivateCopyFunc(const PrivateCopyFunc&);
    PrivateCopyFunc& operator=(const PrivateCopyFunc&);

private:
    int m_Value;
    std::mutex m_Mutex;
};

How Boost Does It?

It can be seen from the Boost noncopyable source that it also uses the same techniques.

C++
  class noncopyable
  {
  protected:
#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) && 
         !defined(BOOST_NO_CXX11_NON_PUBLIC_DEFAULTED_FUNCTIONS)
      BOOST_CONSTEXPR noncopyable() = default;
      ~noncopyable() = default;
#else
      noncopyable() {}
      ~noncopyable() {}
#endif
#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
      noncopyable( const noncopyable& ) = delete;
      noncopyable& operator=( const noncopyable& ) = delete;
#else
  private:  // emphasize the following members are private
      noncopyable( const noncopyable& );
      noncopyable& operator=( const noncopyable& );
#endif
  };

Bonus: When copy Constructor and Assignment Operator are Called

Having done interviews over the years, I discover to my dismay that many job candidates are not aware of when copy constructor and assignment operator are called. Run the code below to see which lines are printed.

C++
class CopyableClass
{
public:
    CopyableClass(int value) : m_Value(value) {}
    CopyableClass(const CopyableClass& that)
    {
        std::cout << "CopyableClass Copy Constructor called!" << std::endl;
        this->m_Value = that.m_Value;
    }
    CopyableClass& operator=(const CopyableClass& that)
    {
        std::cout << "CopyableClass Assignment Operator called!" << std::endl;
        this->m_Value = that.m_Value;
        return *this;
    }

private:
    int m_Value;
};

int main()
{
    CopyableClass a(10);
    CopyableClass b = a; // CopyableClass Copy Constructor called!
    b = a; // CopyableClass Assignment Operator called!

    CopyableClass c(a); // CopyableClass Copy Constructor called!

    return 0;
}

The example code is hosted at Github.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)