Disable copy constructor
C++Copy ConstructorC++ Problem Overview
I have a class :
class SymbolIndexer {
protected:
SymbolIndexer ( ) { }
public:
static inline SymbolIndexer & GetUniqueInstance ( )
{
static SymbolIndexer uniqueinstance_ ;
return uniqueinstance_ ;
}
};
How should I modify it to disable code like:
SymbolIndexer symbol_indexer_ = SymbolIndexer::GetUniqueInstance ( );
and only allow code like :
SymbolIndexer & ref_symbol_indexer_ = SymbolIndexer::GetUniqueInstance ( );
C++ Solutions
Solution 1 - C++
You can make the copy constructor private and provide no implementation:
private:
SymbolIndexer(const SymbolIndexer&);
Or in C++11, explicitly forbid it:
SymbolIndexer(const SymbolIndexer&) = delete;
Solution 2 - C++
If you don't mind multiple inheritance (it is not that bad, after all), you may write simple class with private copy constructor and assignment operator and additionally subclass it:
class NonAssignable {
private:
NonAssignable(NonAssignable const&);
NonAssignable& operator=(NonAssignable const&);
public:
NonAssignable() {}
};
class SymbolIndexer: public Indexer, public NonAssignable {
};
For GCC this gives the following error message:
test.h: In copy constructor ‘SymbolIndexer::SymbolIndexer(const SymbolIndexer&)’:
test.h: error: ‘NonAssignable::NonAssignable(const NonAssignable&)’ is private
I'm not very sure for this to work in every compiler, though. There is a related question, but with no answer yet.
UPD:
In C++11 you may also write NonAssignable
class as follows:
class NonAssignable {
public:
NonAssignable(NonAssignable const&) = delete;
NonAssignable& operator=(NonAssignable const&) = delete;
NonAssignable() {}
};
The delete
keyword prevents members from being default-constructed, so they cannot be used further in a derived class's default-constructed members. Trying to assign gives the following error in GCC:
test.cpp: error: use of deleted function
‘SymbolIndexer& SymbolIndexer::operator=(const SymbolIndexer&)’
test.cpp: note: ‘SymbolIndexer& SymbolIndexer::operator=(const SymbolIndexer&)’
is implicitly deleted because the default definition would
be ill-formed:
UPD:
Boost already has a class just for the same purpose, I guess it's even implemented in similar way. The class is called boost::noncopyable
and is meant to be used as in the following:
#include <boost/core/noncopyable.hpp>
class SymbolIndexer: public Indexer, private boost::noncopyable {
};
I'd recommend sticking to the Boost's solution if your project policy allows it. See also another boost::noncopyable
-related question for more information.
Solution 3 - C++
Make SymbolIndexer( const SymbolIndexer& )
private. If you're assigning to a reference, you're not copying.
Solution 4 - C++
C++ developers learning about reference vs pointer may be tempted to have
class MyClass {
SomeClass acc;
public:
MyClass() : acc() {}
SomeClass &GetAccess( return acc; );
};
As a convenient way to then do:
someblock->{
MyClass inst;
auto acc = inst.GetAccess();
acc.SomeFunction();
}
which will create problems with double frees inside of SomeClass, because you end up with a copy by default...