生成的复制和移动运算符?

时间:2015-08-05 17:08:46

标签: c++ copy-constructor move-semantics copy-assignment

目前我从 Scott Meyers 阅读了有效的现代C ++ 这本书,现在我在:第17项:了解特殊成员函数的生成。

我的误解来自以下部分(理由):

两个复制操作是独立的:声明一个不会阻止编译器生成另一个。因此,如果您声明了复制构造函数,但没有复制赋值运算符,则编写需要复制赋值的代码,编译器将为您生成复制赋值运算符。同样,如果您声明了一个复制赋值运算符,但没有复制构造函数,但您的代码需要复制构造,编译器将为您生成复制构造函数。在C ++ 98中也是如此,在C ++ 11中仍然如此。

这两个移动操作并不是独立的。如果您声明其中任何一个,则会阻止编译器生成另一个。 基本原理是,如果你为你的类声明一个移动构造函数,你就会指出应该如何实现移动构造,这与编译器将生成的默认成员移动不同。如果成员移动构造出现问题,成员移动分配也可能出现问题。因此,声明移动构造函数会阻止生成移动赋值运算符,并声明移动赋值运算符可防止编译器生成移动构造函数。

我认为基本原理部分也可以应用于复制构造函数复制赋值运算符对,不是吗?因此,如果我声明一个复制构造函数,我用它指示默认的成员副本对我来说是不够的。如果我这样说,那么复制赋值运算符也应该是用户定义的。

我认为这是一本很棒的书,但在这一点上,这个理由对我来说并不清楚。请帮帮我解释一下。感谢。

1 个答案:

答案 0 :(得分:3)

  

我认为基本原理部分也可以应用于复制构造函数和复制赋值运算符对,不是吗?

绝对。标准同意你的看法。在[class.copy]中:

  

如果类定义没有显式声明复制构造函数,则会隐式声明非显式的。   如果类定义声明了移动构造函数或移动赋值运算符,则隐式声明的副本   构造函数定义为已删除;否则,它被定义为默认值(8.4)。 如果是,则不推荐使用后一种情况   该类具有用户声明的复制赋值运算符或用户声明的析构函数。

  

如果类定义未明确声明副本赋值运算符,则会隐式声明一个。如果   类定义声明了一个移动构造函数或移动赋值运算符,即隐式声明的副本   赋值运算符定义为已删除;否则,它被定义为默认值(8.4)。 后一种情况是   如果类具有用户声明的复制构造函数或用户声明的析构函数,则不推荐使用。

当然,如果所讨论的“后一种情况”立即被废除,可能会有很多现有的代码会破坏,这就是为什么标准先移动到弃用并且只会在某些任意距离的地方移除它们。未来。

然而,即使是长期弃用且已经删除的功能也有很长的路要走。像char * s = "MyString";

一样