明确的移动ctor是否消除了隐式复制ctor?

时间:2013-09-19 13:19:30

标签: c++ c++11 constructor implicit-declaration

我在接受的答案here中读到:

  

[a]复制构造函数和复制赋值运算符不会为显式声明移动构造函数移动赋值运算符的类生成

我注意到(g ++ 4.7.2),如果你定义一个移动构造函数,它将与例如push_back()一起使用,而如果你所做的只是= delete复制构造函数,那么你不要得到隐式移动构造函数 - 你得到一个错误。 [...这让我想知道如果你没有明确地做任何事情,实际使用哪一个(移动或复制)...]

但是,this online reference没有对定义移动构造函数时隐式定义的复制构造函数而不是做出相同的显式约定。

所以我的问题是,标准保证的第一个报价(包括“或”)?我希望,对于一些需要显式析构函数的类,只需要一个移动构造函数和一个(删除的)移动运算符来完成“五条规则”,并依赖于隐式复制方法 not 被定义。如果我不能依赖它,那么我将不得不明确=delete它们 - 但这是很多可能多余的东西。

2 个答案:

答案 0 :(得分:6)

  

所以我的问题是,标准保证的第一个报价(包括“或”)?

是的,标准可以保证您的第一个引用。

引自标准(草案n3690):

  

12.8复制和移动类对象[class.copy]

     

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

答案 1 :(得分:2)

有趣的后续行动是为什么?

在C ++ 98中是Rule of Three

  

如果您定义以下任何一项,则应定义所有三项:

     
      
  •   
  • 复制构造函数
  •   
  • 复制分配操作员
  •   

这个经验法则的创建是因为许多人只考虑释放析构函数中的资源,并忘记了这种特殊行为对副本的影响。

当C ++ 11即将来临时,许多人认为这个问题是由语言提供的默认定义引起的,事后看来,默认情况下不提供它们会更好。当然,C默认提供它们(对于struct)所以......

...有些人认为,事实上,三者规则可以由编制者强制执行;或者至少,因为改变现有行为可能会破坏现有代码,所以每当谈论移动构造函数或移动赋值运算符(它保证新的C ++ 11代码)时,编译器都可以强制执行“三条规则”的附件。 p>

五法则:

  

如果您定义以下任何一项,则应定义所有五项:

     
      
  •   
  • 移动构造函数
  •   
  • 移动赋值运算符
  •   
  • 复制构造函数
  •   
  • 复制分配操作员
  •   
因此,

几乎完全实现为:

  • 如果您定义移动构造函数或移动赋值运算符,则隐式删除其他4个方法(除非您提供它们)
  • 如果定义析构函数,复制构造函数或复制赋值运算符,则隐式删除移动构造函数和移动赋值运算符(除非您提供它们)

由于向后兼容性原因,第二个语句略微不完整,因为现有的C ++ 98代码(应该在不改变行为的情况下编译为C ++ 11)。