I'd like to make object of class not copyable so I put copy constructor and operator= in private section. However one class is friend of this class so it has access to private methods. Is it good idea to put throw exception in copy constructor and operator= to be sure that object will not be copied?
One approach to make it not copyable is just to declare the copy constructor, but don't implement it at all. That will force a linker error at compile time if anyone tries to use it.
class foo
{
private:
foo(const foo&); // not defined
foo& operator=(const foo&); // not defined
};
#Mysticial have answered this question which is usually done in C++03. But in C++11, you can do this, more nicely:
class foo
{
private:
foo(const foo&) = delete;
foo& operator=(const foo&) = delete;
};
The =delete conveys the message that foo doesn't support copy-semantic, as it has been disabled by explicitly marking it with delete. I've explained this in detail here:
Is there a way to disable constructor synthesizing on a class?
Related
Using C++11.
I have a class I want to clean-up a bit by making the following changes:
From
class MyClass {
public:
// code
private:
MyClass(const MyClass&);
MyClass& operator=(const MyClass&);
// members
};
To
class MyClass {
public:
// code
MyClass(const MyClass&) = delete;
MyClass& operator=(const MyClass&) = delete;
private:
// members
};
Knowing that both are declared but not defined, will this change break binary compatibility?
Does it improves anything?
If you switch from your first version to the second, where you have accessible, user-declared, deleted constructors, code like this will compile in C++11:
MyClass b{};
But if you upgrade to C++20, it won't. That might not be something you want. If you stick with your first version, where the constructors are inaccessible, the declaration of b won't compile in any language version, so you won't have this problem at least.
Here's a demo.
I'm trying to move a std::future member of class to another member of same class.
I need to do that because if I want to call std::vector.push_back(MyClass), I need to delete the copy constructor with a simple reference and create another one with double ref because my class contain a std::future member.
When i move the std::future, G++ says :
call to deleted constructor of 'std::future<int>'
_future(std::move(p_myclass._future));
note: 'future' has been explicitly marked deleted here
future(const future&) = delete
But for me, std::move returns a double ref and not a single. So I don't really know where this error comes from.
I tried the assignement operator = with double ref but doesnt work either.
class MyClass
{
private:
std::future<int> _future;
public:
MyClass(const MyClass&) = delete;
MyClass(const MyClass&&);
MyClass& operator=(MyClass &) = delete;
MyClass& operator=(MyClass &&);
};
MyClass::MyClass(const MyClass &&p_myclass) : _future(std::move(p_myclass._future)) {};
MyClass& MyClass::operator=(MyClass &&p_myclass)
{
this->_future = std::move(p_myclass._future);
return (*this);
};
Of course my std::future is initialised on main constructor, but there is no need to paste it here.
Both doesn't work.
Thanks in advice.
p_myclass is const, and then so is p_myclass._future. That's why it can't be moved from; moving from an object requires modifying it. _future(std::move(p_myclass._future)) attempts to copy it instead, but of course std::future is not copyable.
C++11 scratches an itch that's long bothered me by allowing you to mark implicitly compiler defined methods as verboten with the "= delete" syntax. Wikipedia for more info.
class Foo
{
public:
Foo();
~Foo();
// No copy
Foo(Foo const &) = delete;
Foo& operator=(Foo const &) = delete;
};
Copy and assignment operators for classes that I do not expect to have copied or assigned are always a pain to mess with. It's a lot of boiler-plate code to make them private and then often there's member data that don't have a default constructor that require some hand-waving to make the compiler happy on a function you just want no one to ever call.
class Bar
{
public:
explicit Bar(UniqueResourceID id): m_data(id) { }
~Bar();
protected:
SomeHandle m_data; // no default constructor
// all this crap to keep from being able to copy. Do not use any of these!!
private:
Bar() { } // ERROR: m_data has no default constructor
static UniqueResourceID s_invalidID; // now I'm making the problem worse,
// because I don't actually need this
// for anything real, except to shut
// up some errors.
Bar(Bar const &o): m_data(s_invalidID) { }
Bar& operator =(Bar const &o): { return *this; }
};
Unfortunately, some of the compilers I have to use are not C++11 compilers and don't offer =delete. What's the best way of dealing with these? (Please tell me there's a better way than the second code snippet.)
You are writing all the extra crap because you are actually defining the body of the deleted operators -- I don't think you have to, and what I do is just making the declaration with no implementation anywhere, like this;
class Bar
{
public:
explicit Bar(UniqueResourceID id): m_data(id) { }
~Bar();
protected:
SomeHandle m_data; // no default constructor
private:
Bar();
Bar(Bar const &o);
Bar& operator =(Bar const &o);
};
This is no more verbose than writing the method with = delete appended to it.
Edit: Your definition of
....
private:
Bar() {}
Is actually dangerous as it allows the operator to be called from other methods of within Bar without any errors ever getting generated (linker or compiler)
I have a problem dealing with deprecated since C++11 default generation of copy constructor and copy assignment operator when there is a user-defined destructor.
For most sufficiently simple classes default-generated constructors, operators and destructor are fine. Consider the following reasons to declare destructor:
Making trivial destructor virtual in base class:
// header
class Base1 { public: virtual ~Base1() = default; };
class Base2 { public: virtual ~Base2(); };
// source
Base2::~Base2() = default;
Would all 4 copy and move special methods be generated by compiler in these cases? If yes, then I think it is fine and there is no need to complicate Base1 or Base2.
Printing debug message in destructor:
// header
class D { public: ~D(); };
// source
D::~D() {
#ifdef DEBUG_THIS
std::cout << "D was destructed." << std::endl;
#endif
}
I believe that in this case copy constructor and assignment operator would be generated; but move constructor and assignment operator would not. I want to avoid using deprecated default-generating and disable copying of D. I also want to avoid flooding D with 4 deleted declarations. Is disabling only one copy constructor enough? Is it a good style?
With C++11, a clean way is to follow the pattern used in boost (see here)
You basically create a base class where copy constructor and copy assignment are deleted, and inherit it:
class non_copyable
{
protected:
non_copyable() = default;
~non_copyable() = default;
non_copyable(non_copyable const &) = delete;
void operator=(non_copyable const &x) = delete;
};
class MyClass: public non_copyable
{
...
}
Deleting the copy-constructor and copy-assignment operator is the simplest and clearest way to disable copying:
class X
{
X(X const &) = delete;
void operator=(X const &x) = delete;
};
I don't follow what you are talking about with virtual destructors in the question body . It sounds like you're asking for a way to make your code take up fewer characters of source code, but also be more cryptic to anybody looking at it.
If the list of deleted functions bothers you, you could hide them behind a macro, I guess.
#define NON_COPYABLE_NOR_MOVABLE(T) \
T(T const &) = delete; \
void operator=(T const &t) = delete; \
T(T &&) = delete;
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 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.
You can do it by this(which is used by Caffe: a fast open framework for deep learning):
// Disable the copy and assignment operator for a class.
#define DISABLE_COPY_AND_ASSIGN(classname) \
private:\
classname(const classname&);\
classname& operator=(const classname&)
Usage example:
class CNoCopyable{
public:
CNoCopyable(int i):m_d(i){}
private:
int m_d;
// add this line(pass class name)
DISABLE_COPY_AND_ASSIGN(CNoCopyable);
};
I want to ensure that the following type of call is illegal:
MyClass me;
MyClass you;
me = you; // how to make this illegal?
Is it possible?
Declare the assignment operator private:
class A {
private:
void operator=(const A&);
...
};
but don't provide an implementation - you will get a compile or link-time error if you try to perform an assignment to A.
I prefer to use a macro to do this. This also prevents copying, by making the copy constructor private too:
#define CANNOT_COPY( class ) \
private: \
class(const class&); \
void operator=(const class &) \
I can then say things like:
class A {
CANNOT_COPY( A );
...
};
which is easy to read and easy to search for.
declare the assignment operator as private.
Yes - define a private assignment operator (operator=) or derive from the handy boost::noncopyable class.
As of C++11, my understanding is that the preferred solution is to use the '= delete' construct:
class MyClass {
MyClass (const MyClass&) = delete; // Disable copy constructor
MyClass& operator=(const MyClass&) = delete; // Disable assignment
...
}
Then
MyClass me;
MyClass you;
me = you; // won't compile
Use const.
MyClass const me;
MyClass you;
me = you; // compilation error
I use to derive my noncopyable classes from a common noncopyable class. If not using boost, I usually use this shortcut:
class NonCopyable
{
protected:
/**
* Protected default constructor
*/
NonCopyable() {}
/**
* Protected destructor
*/
~NonCopyable() {}
private:
/**
* Private copy constructor
*/
NonCopyable( const NonCopyable& );
/**
* Private assignment operator
*/
const NonCopyable& operator=( const NonCopyable& );
};
Note that neither the copy constructor nor the assignment operators have an implementation.
The other answers here are all correct. However, it is important to note that you are only prohibiting the specific code you mentioned. Someone can still come along and make a duplicate of your class by using memcpy or other strategies.