【问题标题】:Move constructors and multiple inheritance移动构造函数和多重继承
【发布时间】:2012-04-24 06:36:23
【问题描述】:

概要

当类使用多重继承时,如何安全地设计移动构造函数?

详情

考虑以下场景:

struct T { };
struct U { };

struct X : public T, public U
{
    X(X&& other)
      : T(std::move(other))
      , U(std::move(other)) // already moved?!
    {
    }
};

有没有办法安全地移动构造TU

【问题讨论】:

    标签: c++ c++11 multiple-inheritance move-semantics move-constructor


    【解决方案1】:

    tl;dr:问题中的代码没问题。

    上面的代码很好,因为std::move 本身实际上并没有以任何方式改变other,它只是进行了一次强制转换以使other 成为右值引用,以便T 的移动构造函数和U 被调用而不是它们的复制构造函数。

    T(std::move(other)) 运行时,T 的移动构造函数将被调用(假设它有一个)并且other 中的T 将被移动到this 中的Tother 中的 U 将保持不变,直到运行 U(std::move(other))

    请注意,这意味着当 X 的移动构造函数代码运行时,您不能依赖 other 中的 TU 的成员/成员函数,因为 other 的那些位将具有已经搬家了。


    附带说明,可以通过更改为:

    X(X&& other)
      : T(std::move(static_cast<T&>(other)))
      , U(std::move(static_cast<U&>(other)))
    {
    }
    

    因为此版本不依赖从 X&amp;&amp;T&amp;&amp;/U&amp;&amp; 的隐式向上转换。依赖隐式向上转换可能是一个问题,因为T 和/或U 可能有一个T(X&amp;&amp;) 构造函数或一个accept-anything 模板构造函数,它们中的任何一个都会被选中而不是你的T(T&amp;&amp;) move 构造函数好想打电话。

    【讨论】:

    • 直到有人调用虚函数或移动构造函数/赋值运算符中的某个东西,而继承树中的另一个类对其进行了寻址... rihgt?
    • 为什么不用T(static_cast&lt;T&amp;&amp;&gt;(other)) 而不是T(std::move(static_cast&lt;T&amp;&gt;(other)))U 也一样)?
    • @ildjarn 如果T 是一个具体的类也可以工作,但如果T 是一个模板参数,因为引用折叠可能会出现问题。我试图避免“内联” std::move 以更清楚地说明我正在更改的内容
    • 此示例中没有模板,如果有,您可能需要std::forward 而不是std::move。我个人认为在这里使用move 会让事情变得混乱,但我明白你在说什么。 :-]
    • @ildjarn 我不确定您对std::forward 的看法,但我什至不确定您是在考虑模板构造函数还是模板类。我关于引用折叠的观点是一个废话,因为即使 T 和 U 是模板参数,它们也必须是真正的类,因为它们是继承自的。尽管如此,由于我们正在进行移动,我认为单独进行显式向上转换和移动会更清楚。它还鼓励使用std::move 进行左值到右值的转换,而不是手动编写强制转换,我认为这是一件好事。
    【解决方案2】:

    问题中的代码很好,正如@je4d 的回答所解释的那样。

    你也可以这样写:

    X(X&& other)
      : T(static_cast<T&&>(other))
      , U(static_cast<T&&>(other))
    {
    }
    

    请参阅@jead 的答案评论以获取解释。

    【讨论】:

      【解决方案3】:

      我可以在使用侧音构造函数主体后使用其他对象吗:

      struct T { };
      struct U { };
      
      struct X : public T, public U
      {
          X(X&& other)
            : T(std::move(other))
            , U(std::move(other)) // already moved?!
          {
          member1 = other.member1; //something like. 
      
          }
      };
      

      【讨论】:

        猜你喜欢
        • 2013-02-27
        • 2014-03-08
        • 2011-07-06
        • 1970-01-01
        • 2013-09-06
        • 2014-11-22
        • 2011-09-11
        • 2016-03-24
        相关资源
        最近更新 更多