I'm watching CppCon2014, Michael Caisse, The Canonical Class talk, at 28'31", he shows a diagram showing when user provided some copy control, how would the compiler implicitly provide or not provide the rest:
I don't quite get the cells with "delete" -- seems the standard says, when user provides the move constructor or move assignment, copy constructor and copy assignment will be deleted -- ok, but why?
Let's be more specific.
Q1. when user provides the move constructor, copy constructor and copy constructor will be deleted -- is this intend to avoid a wrong usage, that a lvalue is provided for a constructor or assignment, the lvalue becomes invalid? Is this to explicitly force the parameters passed to constructor or assignment as rvalue?
Q2. when user provides the move assignment, copy assignment will be deleted -- is this the same rational as Q1?
Q3. when user provides the move assignment, copy constructor will be deleted -- why so? A move assignment seems will not mess up with a copy constructor?
It's the least unsafe way, taking into account some unfortunate history.
There is only one reason to user-define a destructor, which is that we are managing a resource that is not itself RAII. If we're managing a resource, it will not copy itself well (or move itself). Those operations will need to be managed manually.
If we're supplying a destructor, the language really ought to implicitly delete copy and move operators. Unhappily, this was not foreseen in the early days so we had the rule of 3 - "if you define a destructor, you must define a copy constructor and copy-assignment".
This rule was to keep us safe from a trap in the language.
There was a proposal to close this hole (IIRC), and as far as I remember, it was rejected as it would break too much existing code (although frankly, all this existing code was dangerously wrong, and this would have been no bad thing).
So we are where we are. The principle is that if you're managing a resource manually, you must manage it in all 5 operations. If you manually write one of these operations, you are expected to write them all.
It's just that for auto-removal of copy constructor/copy-assignment the language remains broken.
The answer of course, is to never manually manage a resource. Since we have smart pointers with custom deleters that will manage resources for us, we rarely need to. When we do, we apply the rules of 5, 3... but we should always prefer the rule of none - use managed resources and don't define any destructors, copy, move or assignment operators, simply let the compiler do the right thing.