What's the Most Reliable Way to Prohibit a Copy Constructor in C++

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):

meow

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

  1. 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.

  2. 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 inheriting boost::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



Leave a reply



Submit