Why user-defined move-constructor disables the implicit copy-constructor?

I’ve upvoted ildjarn’s answer because I found it both accurate and humorous. 🙂

I’m providing an alternate answer because I’m assuming because of the title of the question that the OP might want to know why the standard says so.

background

C++ has implicitly generated copy members because if it didn’t, it would’ve been still-born in 1985 because it was so incompatible with C. And in that case we wouldn’t be having this conversation today because C++ wouldn’t exist.

That being said, implicitly generated copy members are akin to a “deal with the devil”. C++ couldn’t have been born without them. But they are evil in that they silently generate incorrect code in a significant number of instances. The C++ committee isn’t stupid, they know this.

C++11

Now that C++ has been born, and has evolved into a successful grownup, the committee would just love to say: we’re not doing implicitly generated copy members any more. They are too dangerous. If you want an implicitly generated copy member you have to opt-in to that decision (as opposed to opt-out of it). However considering the amount of existing C++ code that would break if this was done, that would be tantamount to suicide. There is a huge backwards compatibility concern that is quite justified.

So the committee reached a compromise position: If you declare move members (which legacy C++ code can’t do), then we’re going to assume that the default copy members are likely to do the wrong thing. Opt-in (with =default) if you want them. Or write them yourself. Otherwise they are implicitly deleted. Our experience to-date in a world with move-only types indicates that this default position is actually quite commonly what is desired (e.g. unique_ptr, ofstream, future, etc.). And the expense of opting-in is actually quite small with = default.

Looking Forward

The committee would love to even say: If you’ve written a destructor, it is likely that the implicit copy members are incorrect, so we will delete them. This is the C++98/03 “rule of three”. However even that would break lots of code. However the committee has said in C++11 that if you provide a user-declared destructor, the implicit generation of copy members is deprecated. That means that this feature could be removed in a future standard. And that any day now your compiler might start issuing “deprecated warnings” in this situation (the standard can not specify warnings).

Conclusion

So be forewarned: C++ has grown up and matured over the decades. And that means that your father’s C++ may need migrating to deal with your child’s C++. It is a slow, gradual process so that you don’t throw up your hands and just port to another language. But it is change, even if slow.

Leave a Comment