How can I make a Class non-cloneable like we can do in Java while creating singleton.
Is there any condition we can put on copy constructor so that an exception can be thrown if user tries to make a copy of an object?
I am a novice in C++ so kindly add any info to this or redirect if an answer is already available for the same.
Just declare copy constructor and copy assign operator private
in C++03
class NonCopyable
{
public:
NonCopyable() { }
private:
NonCopyable(const NonCopyable&);
NonCopyable& operator=(const NonCopyable&);
};
Also you can make a class derive from NonCopyable, AnotherType is un-copyable
class AnotherNonCopyable : private NonCopyable
{
public:
AnotherNonCopyable () {}
}
With C++11:
class NonCopyableType
{
public:
NonCopyableType(const NonCopyableType&) = delete;
NonCopyableType& operator=(const NonCopyableType&) = delete;
};
You can delete the copy constructor and assignment operator:
struct Foo
{
Foo(const& Foo) = delete;
Foo& operator=(const Foo&) = delete;
};
If you don't have C++11 support, make them private, and don't implement them:
struct Foo
{
private:
Foo(const& Foo);
Foo& operator=(const Foo&);
};
Note In C++, class and struct are essentially the same.
Declare the copy-semantics as delete:
//C++11 only
MyClass(MyClass const &) = delete;
MyClass& operator=(MyClass const &) = delete;
That makes the class non-copyable!
//pre-C++11 code
private:
MyClass(MyClass const &); //declare only, don't define it
MyClass& operator=(MyClass const &); //declare only, don't define it
This should also work!
Is there any condition we can put on copy constructor so that an
exception can be thrown if user tries to make a copy of an object.
if you make the copy constructor private, The code will not compile when the programmer tries to make another copy. This is probably better than detecting the error with an exception at runtime.
class foo {
private:
operator = ( const foo& f);
};
Related
I have a class with deleted copy constructors and I'm trying to put a mutex member in something like this:
struct A {
A(const A &other) = delete;
A& operator=(const A &other) = delete;
A(A&& other) = default;
A& operator=(A &&other) = default;
std::mutex lock;
};
The compiler is complaining that I'm trying to call the deleted copy constructor, which I summarise to be due to the std::mutex type being non-movable. How can I make the mutex member play with the move constructors with minimal fuss? I don't actually want to move the mutex member itself into the newly constructed object, and would actually like each moved object to just construct it's own mutex
I don't actually want to move the mutex member itself into the newly constructed object, and would actually like each moved object to just construct it's own mutex
Then simply define your move constructor to construct a new mutex:
struct A {
A(const A &other) = delete;
A& operator=(const A &other) = delete;
A(A&& other)
: lock()
{
}
A& operator=(A &&other) = delete;
std::mutex lock;
};
Move assignment will still be a problem and should probably just be deleted. Unless you can answer the question: what happens to the existing mutex member when you're being assigned a new value? Particularly: what if you are assigned a new value while the existing mutex is locked?
As an alternative to providing custom move operations for your class, you could create a generic wrapper:
template <class T>
class PerObject
{
T data;
public:
PerObject() = default;
PerObject(const PerObject&) {}
PerObject& operator= (const PerObject&) { return *this; }
T& operator* () const { return data; }
T* operator-> () const { return &data; }
};
And use it like this:
struct A {
A(const A &other) = delete;
A& operator=(const A &other) = delete;
A(A&& other) = default;
A& operator=(A &&other) = default;
PerObject<std::mutex> lock;
};
The wrapper's copy (and move) operations are no-ops, so the object containing the wrapper will always contain the one it started with.
Caveat: However, based on how your class uses the mutex, the above could actually be dangerous. If the mutex is used to protect other data within the class, then it should likely be locked while the object is being assigned to, so you will have to provide manual move operations anyway. In such case, the code would likely look something like this:
struct A {
A(A&& other) : lock{}, /* anything else you need to move-construct */
{
// Note: it might even be necessary to lock `other.lock` before moving from it, depending on your class's exact semantics and expected use.
}
A& operator=(A &&other)
{
if (this == &other) return *this; // Otherwise, double-locking would be possible
// If you need to lock only this object:
std::unique_lock<std::mutex> l(lock);
// Alternatively, if you need to lock both objects:
std::scoped_lock l(lock, other.lock);
// Now move data from other to this
return *this;
}
std::mutex lock;
};
One way is to make your move constructor to create new mutex when called.
A(A&& other): lock()
{
//... move other things
}
You can also use a std::unique_ptr() to the std::mutex since it is movable.
struct A {
A(const A &other) = delete;
A& operator=(const A &other) = delete;
A(A&& other) = default;
A& operator=(A &&other) = default;
std::unique_ptr<std::mutex> lock;
};
A::A() : lock(new std::mutex())
With this approach you'll not create new mutex each time you move the object which will remove some of the overhead.
I need a noncopyable class which has a declared destructor, and naive approach doesn't work: see https://ideone.com/mU8aoc. What's the problem with the destructor, why moving doesn't work the same way as without it? And of course, how to fix it?
For reference, the complete code (same as by the ideone link above):
class noncopyable {
public:
noncopyable(noncopyable &&) noexcept;
noncopyable &operator=(noncopyable &&) noexcept;
protected:
noncopyable() = default;
~noncopyable() = default;
noncopyable(const noncopyable &) = delete;
noncopyable &operator=(const noncopyable &) = delete;
};
class C: noncopyable {
public:
// compiles if this line is uncommented
// C(C&& c);
C() {}
// also compiles if this is commented
~C() {}
};
C a() {
return {};
}
C b() {
return a();
}
int main() {
return 0;
}
For your code to work, class C must be moveable. When it has no declared destructor, it gets a compiler-generated implicit move constructor (and move assignment operator). But when it has a declared ("custom" in your parlance) destructor, the move constructor (and move assignment operator) are no longer provided implicitly. This is for your safety: it is assumed that if you need an explicit destructor you will need explicit move functions as well.
Reference: http://en.cppreference.com/w/cpp/language/move_constructor
This is what I am trying to do:
class A{
public:
A(){/*need to initialize something here*/}
};
int main(){
A a; //OK
a=A(); //not OK
a=A(b); //not OK
///Only A a; needs to be allowed.
return 0;
}
I need to initialize something while preventing object initialization with copy constructor and also prevent assignment to existing object.
Note: It would be good if I can do this without >=C++11.
Since C++11, just delete assignment operator:
class A{
public:
A(){/*need to initialize something here*/}
A& operator =(const A&) = delete;
};
You can achieve your goal by declaring the assignment operator and the copy constructor in the private part, and not defining them.
For example:
class A {
private:
A(A&); // declared, not defined
void operator= (A&); // declared, not defined
public:
A() { //do regular stuff }
}
However, if you are using C++11/C++14, you can use the delete keyword for more explicit case of this:
class A {
public:
A() { //do regular stuff }
A(A&) = delete;
void operator= (A&) = delete;
}
Since the move constructor and the move assignment operators will not be generated if you declare any of the destructor / copy constructor / assignment operator, you don't need to the same thing for them.
You can just = delete; the copy assignment operator:
class A {
// ...
void operator=(A) = delete;
};
Alternatively, if you don't use C++11 you can make the copy assignment private.
You can define the assignment operator as deleted. For example
class A{
public:
A(){/*need to initialize something here*/}
A & operator =( const A & ) = delete;
};
Or you can declare it private.
class A{
public:
A(){/*need to initialize something here*/}
private:
A & operator =( const A & );
};
If I want to forbid copy construction/assignment then is:
class foo
{
public:
foo(const foo&) = delete;
foo& operator = (const foo&) = delete;
};
The same as:
class foo
{
private:
foo(const foo&) = default;
foo& operator = (const foo&) = default;
};
Which is the right way and why?
The right way is the first solution : the copy constructor and assignment operators are not defined, so any attempt to use them will not compile.
class foo
{
public:
foo(const foo&) = delete;
foo& operator = (const foo&) = delete;
};
The second is declaring and defining the implicitly generated forms as private :
An object of type foo is allowed to copy itself.
Any friend class or method is also allowed to copy a foo
So copy construction/assignment is still possible.
You could also use boost::noncopyable as a base class, it does exactly that with c++11 (see the source code here)
When I want to disallow class copy in C++, I usually declare a private operator= and a copy constructor and I don't implement them:
class MyClass
{
char* _str;
int _len;
MyClass(const MyClass& rhs); //No implementation
MyClass& operator=(const MyClass& rhs); //No implementation
public:
MyClass();
MyClass(const char *);
}
Is this considered a bad style? Is there another way to do this?
In C++11 you can explicitly delete these functions (which is preferred over omitting the implementation, because it is more readable, and it will always generate a compiler-error, and not just a linker-error):
class MyClass
{
char* _str;
int _len;
MyClass(const MyClass& rhs) = delete;
MyClass& operator=(const MyClass& rhs) = delete;
public:
MyClass();
MyClass(const char *);
}
In C++03 you can use a base-class such as boost::noncopyable to achieve the same effect. This might be more readable (this is essentially the same approach as yours - this base-class has private copy-constructor and assignment-operator, so inheriting from it will make your class uncopyable):
class MyClass : boost::noncopyable
{
char* _str;
int _len;
public:
MyClass();
MyClass(const char *);
}
The difference between shallow and deep copying in C++ rests entirely in how you implement your copy-constructor (because your assignment operator should be implemented using your copy-constructor). If you don't have one, neither shallow nor deep copying is possible, if you have, it depends on how it is implemented.
You can create a preprocessor macro to achieve the same thing, e.g.
#define DISABLE_COPY_AND_ASSIGN(className) private: \
className(const className&); \
className& operator=(const className&);
and then use it like this:
class MyClass
{
DISABLE_COPY_AND_ASSIGN(MyClass)
public:
....
};
You can derive from boost::noncopyable as well:
class MyClass : boost::noncopyable
{
public:
....
};
Moreover, in C++11, you can use = delete:
MyClass(const MyClass&) = delete;
MyClass& operator=(const MyClass&) = delete;
There are two ways, and both would cause a compilation errors :
C++11 way:
class MyClass
{
char* _str;
int _len;
MyClass(const MyClass& rhs) = delete;
MyClass& operator=(const MyClass& rhs) = delete;
public:
MyClass();
MyClass(const char *);
};
C++03 way:
class MyClass
{
char* _str;
int _len;
public:
MyClass();
MyClass(const char *);
MyClass(const MyClass& rhs); //No implementation
MyClass& operator=(const MyClass& rhs); //No implementation
}
If you just declare copy constructors public, you'll get linker errors, but the compilation will pass. Since the compilation happens before linking, breaking the compilation is better, because you'll catch the errors sooner.