For standard copy constructors and assignment operators, I always think about implementing them or deleteing the defaults out of existence, if my class implements a destructor.
For the new move constructor and move operator, what is the right way to think about whether or not an implementation is necessary?
As a first pass of transitioning a system from pre-C++0x, could I just delete the default move constructor and move operator or should I leave them alone?
You don’t have to worry about it, in the sense that when you user-declare a destructor (or anything else listed in 12.8/9), that blocks the default move constructor from being generated. So there’s not the same risk as there is with copies, that the default is wrong.
So, as the first pass leave them alone. There may be places in your existing code where C++11 move semantics allow a move, whereas C++03 dictates a copy. Your class will continue to be copied, and if that caused no performance problems in C++03 then I can’t immediately think of any reason why it would in C++11. If it did cause performance problems in C++03, then you have an opportunity to fix a bug in your code that you never got around to before, but that’s an opportunity, not an obligation 😉
If you later implement move construction and assignment, they will be moved, and in particular you’ll want to do this if you think that C++11 clients of your class are less likely to use “swaptimization” to avoid copies, more likely to pass your type by value, etc, than C++03 clients were.
When writing new classes in C++11, you need to consider and implement move under the same criteria that you considered and implemented
swapin C++03. A class that can be copied implements the C++11 concept of “movable”, (much as a class that can be copied in C++03 can be swapped via the default implementation instd), because “movable” doesn’t say what state the source is left in – in particular it’s permitted to be unchanged. So a copy is valid as a move, it’s just not necessarily an efficient one, and for many classes you’ll find that unlike a “good” move or swap, a copy can throw.You might find that you have to implement move for your classes in cases where you have a destructor (hence no default move constructor), and you also have a data member which is movable but not copyable (hence no default copy constructor either). That’s when move becomes important semantically as well as for performance.