Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the most reliable way to prohibit a copy constructor in C++?

Sometimes it's necessary to prohibit a copy constructor in a C++ class so that class becomes "non-copyable". Of course, operator= should be prohibited at the same time.

So far I've seen two ways to do that. Way 1 is to declare the method private and give it no implementation:

class Class {
//useful stuff, then
private:
    Class( const Class& ); //not implemented anywhere
    void operator=( const Class& ); //not implemented anywhere
};

Way 2 is to declare the method private and give it "empty" implementation:

class Class {
//useful stuff, then
private:
    Class( const Class& ) {}
    void operator=( const Class& ) {}
};

IMO the first one is better - even if there's some unexpected reason that leads to the copy constructor being called from the same class member function there'll be a linker error later on. In the second case this scenario will be left unnoticed until the runtime.

Are there any serious drawbacks in the first method? What's a better way if any and why?

like image 767
sharptooth Avatar asked Apr 18 '11 11:04

sharptooth


People also ask

How do I block a copy constructor?

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.

What is the correct argument for copy constructor?

Definition. Copying of objects is achieved by the use of a copy constructor and an assignment operator. A copy constructor has as its first parameter a (possibly const or volatile) reference to its own class type. It can have more arguments, but the rest must have default values associated with them.

When should you delete copy constructor?

Copy constructor (and assignment) should be defined when ever the implicitly generated one violates any class invariant. It should be defined as deleted when it cannot be written in a way that wouldn't have undesirable or surprising behaviour.

What are the disadvantages of copy constructor?

The only disadvantage I can think of to a copy constructor is that some large objects can be expensive to copy (eg. copying a long string involves allocating a large block of memory then copying all the content).


6 Answers

The first one is better

Even better is C++0x 'delete' keyword:

class Class {
// useful stuff, then
public:
    Class(const Class&) = delete;
    void operator=(const Class&) = delete;
};
like image 141
sehe Avatar answered Oct 05 '22 20:10

sehe


The first method is how Boost solves it (source code), as far as I know, there's no drawbacks. In fact, the linker errors are the big advantage of that method. You want the errors to be at link time, not when your client is executing your code and it suddenly crashes.

In case you are using Boost, you can save yourself some typing. This does the same as your first example:

#include <boost/utility.hpp>

class Class : boost::noncopyable {
// Stuff here
}
like image 26
AVH Avatar answered Oct 05 '22 22:10

AVH


You can always inherit from boost::noncopyable.

Otherwise I've never seen a reason number 2 is better than number 1 as it will allow you to "copy construct" an object within friend or class methods even though it won't actually create a true copy of the object.

like image 37
Mark B Avatar answered Oct 05 '22 21:10

Mark B


As other answers suggest something else, and doesn't really attempt to answer the question, so here is my attempt:

So which approach is better? It depends on how you define prohibit copy?

If you want to prevent others (only non-friend classes and functions) from copying while allowing friends and member-functions to copy, then second approach is the way to go.

If you want to prevent everyone (friends, non-friends, member-functions) from copying, then first approach is the only correct solution.

Note that the second approach does not prevent friends and member-functions from copying (that is, from calling the copy-functions). 1

1. If you don't properly define them in the second case, then copy wouldn't work, as expected, but that is a different thing altogether. But the point is that second case doesn't prevent from calling the copy-functions. The compiler wouldn't generate any error message.

like image 26
Nawaz Avatar answered Oct 05 '22 21:10

Nawaz


There is no drawback in your first approach, I has been using that to make "non-copyable" class ..

like image 25
Jhaliya - Praveen Sharma Avatar answered Oct 05 '22 21:10

Jhaliya - Praveen Sharma


Personally I think you've answered your own question, and should use the first approach.

If you don't want it to be copyable at all, as you said it will throw a linker error. However if you use the second approach and you DO end up using the copy constructor by accident, it WILL compile and it WILL run; and you'll have absolutely no indication of where the inconsistency came from until you bust open a debugger. Or as sehe said, if you can use a modern compiler, use C++11's '= delete' notation.

like image 20
nevelis Avatar answered Oct 05 '22 20:10

nevelis