I have the following Singleton policy-class implementation:
template <typename T> class Singleton { Singleton(){}; // so we cannot accidentally delete it via pointers Singleton(const Singleton&) = delete; // no copies Singleton& operator=(const Singleton&) = delete; // no self-assignments Singleton(Singleton&&) = delete; // WHY? Singleton& operator=(Singleton&&) = delete; // WHY? public: static T& getInstance() // singleton { static T instance; // Guaranteed to be destroyed. // Instantiated on first use. // Thread safe in C++11 return instance; } };
which I then use via the curiously recurring template pattern (CRTP)
class Foo: public Singleton<Foo> // now Foo is a Singleton { friend class Singleton<Foo>; ~Foo(){} Foo(){}; public: // rest of the code };
I cannot figure out why I should delete the move constructor and assignment operator. Can you give me a single example where I end up breaking the singleton if I don't delete (don't define at all) the move ctor and assignment operator?
A move constructor enables the resources owned by an rvalue object to be moved into an lvalue without copying.
The move constructor and move assignment operator are simple. Instead of deep copying the source object (a) into the implicit object, we simply move (steal) the source object's resources. This involves shallow copying the source pointer into the implicit object, then setting the source pointer to null.
The constructor, copy constructor and assignment operator are all private to ensure that the programmer using the singleton class can only create a single instance of the class using only the Instance() function.
A move constructor allows the resources owned by an rvalue object to be moved into an lvalue without creating its copy. An rvalue is an expression that does not have any memory address, and an lvalue is an expression with a memory address.
If you declare a copy constructor (even if you define it as delete
d in the declaration), no move constructor will be declared implicitly. Cf. C++11 12.8/9:
If the definition of a class
X
does not explicitly declare a move constructor, one will be implicitly declared as defaulted if and only if— X does not have a user-declared copy constructor,
— ...
Since you do have a user-declared copy constructor, there won't be a move constructor at all if you don't declare one. So you can just get rid of the move constructor declaration-definition entirely. Same for the move-assignment operator.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With