在阅读 boost/shared_ptr.hpp 时,我看到了这段代码:
// 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 中,移动禁用隐式复制”是什么意思?在 C++11 中我们是否应该总是自己编写复制 ctor 来防止这种情况?
最佳答案
我赞成 ildjarn 的回答,因为我发现它既准确又幽默。 :-)
我提供了一个替代答案,因为我假设 OP 可能想知道为什么标准这样说的问题的标题。
背景
C++ 已经隐式生成了复制成员,因为如果它没有,它会在 1985 年死产,因为它与 C 不兼容。在那种情况下,我们不会今天有这个话题,因为 C++ 不存在。
话虽如此,隐式生成的拷贝成员类似于“与魔鬼打交道”。没有它们,C++ 就不可能诞生。但它们是邪恶的,因为它们在大量实例中默默地生成错误代码。 C++ 委员会并不愚蠢,他们知道这一点。
C++11
既然 C++ 已经诞生,并且已经发展成为一个成功的成年人,委员会只想说:我们不再做隐式生成的复制成员了。他们太危险了。如果您想要一个隐式生成的拷贝成员,您必须选择加入该决定(而不是选择退出)。但是考虑到如果这样做会破坏现有 C++ 代码的数量,那无异于自杀。 巨大的向后兼容性问题是完全合理的。
因此委员会达成了妥协的立场:如果您声明 move 成员(旧版 C++ 代码无法做到这一点),那么我们将假设默认的 copy 成员可能会做错事。如果需要,可选择加入(使用 =default
)。或者自己写。否则,它们将被隐式删除。迄今为止,我们在只移动类型的世界中的经验表明,这个默认位置实际上是非常常见的(例如 unique_ptr
、ofstream
、future
等)。并且使用 = default
选择加入的费用实际上非常小。
展望 future
委员会甚至想说:如果您编写了析构函数,则隐式复制成员很可能不正确,因此我们将删除它们。这是 C++98/03 “三法则”。然而,即使这样也会破坏很多代码。然而,委员会在 C++11 中表示,如果您提供用户声明的析构函数,则复制成员的隐式生成已弃用。这意味着可以在未来的标准中删除此功能。并且现在任何一天你的编译器都可能在这种情况下开始发出“不推荐使用的警告”(标准不能指定警告)。
结论
因此请注意:C++ 已经成长和成熟了几十年。这意味着您父亲的 C++ 可能需要迁移以处理您 child 的 C++。这是一个缓慢而渐进的过程,因此您不会举手而只是移植到另一种语言。但它正在发生变化,即使速度很慢。
关于c++ - 为什么用户定义的移动构造函数会禁用隐式复制构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11255027/