3

When I want to disallow class copy in C++, I usually declare a private operator= and a copy constructor and I don't implement them:

class MyClass
{
  char* _str;
  int _len;
  MyClass(const MyClass& rhs);            //No implementation
  MyClass& operator=(const MyClass& rhs); //No implementation
public:
  MyClass();
  MyClass(const char *);
}

Is this considered a bad style? Is there another way to do this?

Maroun
  • 94,125
  • 30
  • 188
  • 241

3 Answers3

10

In C++11 you can explicitly delete these functions (which is preferred over omitting the implementation, because it is more readable, and it will always generate a compiler-error, and not just a linker-error):

class MyClass
{
  char* _str;
  int _len;
  MyClass(const MyClass& rhs) = delete;
  MyClass& operator=(const MyClass& rhs) = delete;
public:
  MyClass();
  MyClass(const char *);
}

In C++03 you can use a base-class such as boost::noncopyable to achieve the same effect. This might be more readable (this is essentially the same approach as yours - this base-class has private copy-constructor and assignment-operator, so inheriting from it will make your class uncopyable):

class MyClass : boost::noncopyable
{
  char* _str;
  int _len;
public:
  MyClass();
  MyClass(const char *);
}

The difference between shallow and deep copying in C++ rests entirely in how you implement your copy-constructor (because your assignment operator should be implemented using your copy-constructor). If you don't have one, neither shallow nor deep copying is possible, if you have, it depends on how it is implemented.

Community
  • 1
  • 1
Björn Pollex
  • 75,346
  • 28
  • 201
  • 283
  • Does `noncopyable` prevent both *shallow* and *deep* copying? And for c++03 is it better to use a base-class or not to provide an implementation as I did above? – Maroun Nov 19 '12 at 15:26
3

You can create a preprocessor macro to achieve the same thing, e.g.

#define DISABLE_COPY_AND_ASSIGN(className) private: \
    className(const className&); \
    className& operator=(const className&);

and then use it like this:

class MyClass
{
   DISABLE_COPY_AND_ASSIGN(MyClass)
public:
   ....
};

You can derive from boost::noncopyable as well:

class MyClass : boost::noncopyable
{
public:
   ....
};

Moreover, in C++11, you can use = delete:

MyClass(const MyClass&) = delete;
MyClass& operator=(const MyClass&) = delete;
Mr.C64
  • 41,637
  • 14
  • 86
  • 162
2

There are two ways, and both would cause a compilation errors :

C++11 way:

class MyClass
{
  char* _str;
  int _len;
  MyClass(const MyClass& rhs) = delete;
  MyClass& operator=(const MyClass& rhs) = delete;
public:
  MyClass();
  MyClass(const char *);
};

C++03 way:

class MyClass
{
  char* _str;
  int _len;
public:
  MyClass();
  MyClass(const char *);

  MyClass(const MyClass& rhs);            //No implementation
  MyClass& operator=(const MyClass& rhs); //No implementation
}

If you just declare copy constructors public, you'll get linker errors, but the compilation will pass. Since the compilation happens before linking, breaking the compilation is better, because you'll catch the errors sooner.

Tommy
  • 99,986
  • 12
  • 185
  • 204
BЈовић
  • 62,405
  • 41
  • 173
  • 273
  • I don't really understand why moving the copy constructor and the = operator to public is better, can you please explain it? – Maroun Nov 19 '12 at 15:19
  • @Maroun85 The last paragraph might not be so clear. I changed it a bit. They should be private to make the compilation fail. If they are public, then the linking phase will fail – BЈовић Nov 19 '12 at 15:35