为什么用户定义的移动构造函数禁用隐含拷贝构造函数? [英] Why user-defined move-constructor disables the implicit copy-constructor?
问题描述
虽然我读升压/ shared_ptr.hpp,我看到这个code:
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
什么是评论生成的拷贝构造函数,析构函数除了在C ++ 11,移动禁用隐式副本精是什么意思吗?我们将永远写拷贝构造函数自己,prevent在C ++ 11这种情况呢?
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?
推荐答案
我upvoted ildjarn的答案,因为我发现它既准确又幽默。 : - )
I've upvoted ildjarn's answer because I found it both accurate and humorous. :-)
我提供一个备用的答案,因为我假设,因为这个问题的标题是,OP可能想知道的为什么的标准是这么说的。
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.
背景
C ++含蓄生成的拷贝成员,因为如果它没有,它会被仍然诞生于1985年已经因为它的所以与C和不兼容在这种情况下,我们不会今天讨论这个,因为C ++就不会存在。
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.
话虽这么说,隐式生成副本成员是类似于一个魔鬼交易。 C ++已经不能生下来就没有他们。但他们在他们默默实例的数量显著生成不正确的code邪恶。在C ++委员会不傻,他们知道这一点。
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
现在++已经诞生,并已演变成一个成功的大人是C,委员会将只是爱说:我们没有做隐式生成副本的成员了。他们是太危险了。如果你想要一个隐式生成副本会员,您可以选择加入该决定(而不是选择退出的话)。不过考虑到现有的C ++ code,如果这样做的目的是将破坏量,这无异于自杀。有一个的巨大的向后兼容性担忧是很有道理的。
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.
因此,委员会达成妥协的位置:如果你声明的举动成员(其中传统的C ++ code不能做的),那么我们将假设默认复印成员,很可能做错事。选择加入(与 =默认
)如果你想他们。或者自己写他们。否则,它们被隐式删除。我们的最新经验与唯才是举类型的世界表明,此默认位置其实是相当普遍所期望的那样(如的unique_ptr
,的ofstream
,未来
等)。并选入的费用实际上是相当小的 =默认
。
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
.
展望
该委员会很想甚至说:如果你写一个析构函数,它很可能是隐式副本的成员是不正确的,所以我们将其删除。这是C ++ 98/03三法则。然而,即使这会破坏很多code的。然而,委员会已表示,在C ++ 11,如果你提供了一个用户声明的析构函数,复制成员的隐代是德precated 。这意味着,该功能可以在一个未来的标准被移除。而且现在任何一天你的编译器可能开始在这种情况下发放德precated警告(标准不能指定警告)。
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).
结论
所以事先警告:C ++已经长大了,成熟了过去的几十年。这意味着,你父亲的C ++可能需要迁移到处理您的孩子的C ++。这是一个缓慢的,渐进的过程,让你不扔你的手,只是移植到另一种语言。但它的是的变化,即使缓慢的。
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.
这篇关于为什么用户定义的移动构造函数禁用隐含拷贝构造函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!