【问题标题】:Are move constructors/assignment operators generated for derived classes是否为派生类生成移动构造函数/赋值运算符
【发布时间】:2012-05-22 10:16:26
【问题描述】:

如果 X 类派生自 Y 类,并且 Y 类具有以下任何一种:

  • 用户声明的复制构造函数,
  • 用户声明的复制赋值运算符,
  • 用户声明的析构函数
  • 用户声明的移动构造函数,
  • 用户声明的移动赋值运算符,

如果 X 类没有声明上述任何内容,移动构造函数和移动赋值运算符是否会被隐式默认?

例如

struct Y
{
     virtual ~Y() {}

     // .... stuff

};

struct X : public Y
{
   // ... stuff but no destructor, 
   //               no copy/move assignment operator 
   //               no copy/move constructor

   // will X have a default move constructor / assignment operator?
};

我目前正在使用 gcc,但我主要感兴趣的是正确的行为应该是什么(而不是特定编译器是否符合标准)..

【问题讨论】:

  • 与您的问题无关,但如果您不知道 C++11 的情况,您现在可以使用 virtual ~Y() = default; 而不是自己定义析构函数(尽管您的编译器可能没有支持它)。
  • @Luc Danton 出于兴趣,如果我使用virtual ~Y() = default; 会触发编译器隐式默认移动构造函数/赋值运算符吗?还是我需要明确默认这些操作?
  • @mark - 不会,因为明确默认的析构函数是用户定义的析构函数。

标签: c++ c++11


【解决方案1】:

就派生类而言,属性或基类具有用户定义或隐式特殊功能这一事实并不重要。重要的是他们的存在。

兼容的 C++11 编译器应该自动为结构和类提供移动构造函数和赋值运算符,如果可能的话(这在标准中明确定义),即使只有具有动态分配缓冲区的类才能真正从中受益(移动int 只是复制它)。

因此,如果您的类嵌入了std::stringstd::unique_ptr(例如),那么它的移动构造函数将调用嵌入的stringunique_ptr 移动构造函数,它会很高效...免费.

因此,只需更改编译模式即可略微提高性能。

【讨论】:

    【解决方案2】:

    是的,它们在 §12.8.9 中:

    如果类 X 的定义没有显式声明移动构造函数,则会隐式声明 默认当且仅当

    • X 没有用户声明的复制构造函数,
    • X 没有用户声明的复制赋值运算符,
    • X 没有用户声明的移动赋值运算符,
    • X 没有用户声明的析构函数,并且
    • 移动构造函数不会被隐式定义为已删除。

    和§12.8.10

    类 X 的隐式声明的移动构造函数将具有以下形式

    X::X(X&&)
    

    同样,对于 12.8.20 中的移动赋值运算符:

    如果类 X 的定义没有显式声明移动赋值运算符,则当且仅当

    • X 没有用户声明的复制构造函数,
    • X 没有用户声明的移动构造函数,
    • X 没有用户声明的复制赋值运算符,
    • X 没有用户声明的析构函数,并且
    • 移动赋值运算符不会被隐式定义为已删除。

    基类不直接进入它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-05-16
      • 2016-05-19
      • 2017-05-15
      • 2016-10-06
      • 1970-01-01
      • 2021-09-05
      • 2014-08-04
      • 2020-09-06
      相关资源
      最近更新 更多