While I'm reading boost/shared_ptr.hpp, i saw this code:
// generated copy constructor, destructor are fine...
#if defined( BOOST_HAS_RVALUE_REFS )
// ... except in C++0x, move disables the implicit copy
shared_ptr( shared_ptr const & r ): px( r.px ), pn( r.pn ) // never throws
{
}
#endif
What does the comment "generated copy constructor, destructor are fine except in C++11, move disables the implicit copy" mean here? Shall we always write the copy ctor ourselves to prevent this situation in C++11?
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.