What's the most reliable way to prohibit a copy constructor in C++?
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
}
Most concise way to disable copy and move semantics
According to this chart (by Howard Hinnant):
The most concise way is to =delete
move assignment operator (or move constructor, but it can cause problems mentioned in comments).
Though, in my opinion the most readable way is to =delete
both copy constructor and copy assignment operator.
Most concise way to disable copying class in C++11
Only copy constructor and copy assignment operator will be generated when destructor is explicitly defaulted. And even then their generation is deprecated. So, in order to have virtual destructor and all default methods, one should write the following:
struct Base
{
Base()=default;
virtual ~Base() = default;
Base(const Base&)=default;
Base& operator=(const Base&)=default;
Base(Base&&)=default;
Base& operator=(Base&&)=default;
};I would definitely use a macro for more than one such
Base
class.In case when destructor is defined by user, 2 special methods are still generated. There are the following ways to disable deprecated generating copy constructor and copy assignment operator:
delete move constructor OR move assignment operator (not quite self-explanatory but very short):
Base(Base&&)=delete; // shorter than deleting assignment operator
delete both copy constructor and copy assignment operator:
Base(const Base&)=delete;
Base& operator=(const Base&)=delete;
Note that you have to explicitly declare default constructor if you need it, e.g.
Base()=default;
.Macro or inheriting special class can be used as well for this purpose but I personally prefer deleting move constructor to implementing my own macro or base class. When using Qt or boost, I would prefer
Q_DISABLE_COPY(Base)
and inheritingboost::noncopyable
respectively, because they are already implemented, widely known and recognizable.
http://accu.org/index.php/journals/1896 - detailed explanation and rationale for these issues.
Disable copy constructor
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;
How to prevent implementing a method that is intended to be non-implemented in C++?
In C++0x there is the new delete
keyword, that does just this
What's the most reliable way to prohibit a copy constructor in C++?
is it possible to forbid assignment if there is no explicit copy constructor? c++
You could mark the copy-constructor and copy-assignment operator as deleted:
class A
{
public:
...
A(const A&) = delete;
A& operator=(const A&) = delete;
};
If your compiler doesn't support C++11 features like this, just make the functions private
.
Other way to prohibit a certain C++ class construction except than declaring the constructor private?
Simply don't define this:
B():host(A()) {} // This is ugly and not needed !!
That is, the following should do what you want to do:
class B {
B(const A& a): host(a) {}
private:
//B():host(A()) {} // This is ugly and not needed !!
const A& host;
};
The idea is if you've defined a constructor that takes parameter(s), then the default constructor is not generated by the compiler. That means, instances of the above class cannot be default created!
B b1; //error - needs default constructor which doesn't exist!
B b2(a); //ok - only way to create an instance!
C++11 solution
In C++11, you can explicity tell the compiler not to generate a particular constructor as:
struct B
{
B(const A &a) {}
B() = delete; //disable
};
Not only that. There is more to it, as explained below:
Now the interesting part
You can also selectively disable constructor(s) for selected types which makes delete
more interesting. Consider this,
struct A
{
A (int) {}
};
Object of this class can be created not only with int
argument, but any type which implicitly converts to int
. For example,
A a1(10); //ok
A a2('x'); //ok - char can convert to int implicitly
B b;
A a3(b); //ok - assume b provides user-defined conversion to int
Now suppose, for whatever reason, I don't want the users of class A
to create objects with char
or class B
, which fortunately or unfortunately can implicitly convert to int
, then you can disable them as:
struct A
{
A(int) {}
A(char) = delete; //disable
A(const B&) = delete; //disable
};
Now here you go:
A a1(10); //ok
A a2('x'); //error
B b;
A a3(b); //error - assume (even if) b provides user-defined conversion to int
Online Demo : http://ideone.com/EQl5R
The error messages are very clear:
prog.cpp:9:5: error: deleted function 'A::A(char)'
prog.cpp:10:5: error: deleted function 'A::A(const B&)'
Can I prevent a copy constructor with some exception?
You could use a smart pointer like std::shared_ptr
or write a proxy class.
E.g.:
class Foo {
public:
std::string name() const;
};
typedef std::shared_ptr<Foo> SharedFoo;
or
class SharedFoo {
public:
std::string name() const { return instance->name(); }
private:
std::shared_ptr<Foo> instance;
};
prevent accidental object copying in C++
If your coding standard states "be aware of the ways (accidental) copying can be prevented", I'm guessing they aren't just talking about preventing copies from within the classes itself, but about the performance implications of unnecessary / accidental copies when using the classes.
One of the main causes of unnecessarily wasted performance in the code of people new to C++ is unnecessary copying, usually through temporaries. Compilers are getting better and better at deciding when temporaries are not necessary (see "Want speed? Pass by Value", thanks to Konrad's comment), but the best thing to do is to learn to be aware of the inner workings of copying and temporaries in C++ (among others). For me, reading Efficient C++ really got me started.
Related Topics
Most Efficient/Elegant Way to Clip a Number
"Inline" Keyword VS "Inlining" Concept
Why Does Libc++'s Implementation of Std::String Take Up 3X Memory as Libstdc++
How to Use Covariant Return Types with Smart Pointers
Why Isn't C/C++'s "#Pragma Once" an Iso Standard
Logical And, Or: Is Left-To-Right Evaluation Guaranteed
C++ Typedef Interpretation of Const Pointers
C++ Template Friend Operator Overloading
What Is the Scope of a 'While' and 'For' Loop
How to Use Something Like Std::Vector<Std::Mutex>
Do Class Functions/Variables Have to Be Declared Before Being Used
Virtual Tables and Memory Layout in Multiple Virtual Inheritance