移动构造函数的派生类困惑

5
我知道C++中的移动语义和移动构造函数,但是我有一些困惑:
class Derived: public Base {
    std::vector<int> vec;
    std::string name;
    // ...
public:
    // ...
    // move semantics
    Derived(Derived&& x)              // rvalues bind here
        : Base(std::move(x)), 
        vec(std::move(x.vec)),
        name(std::move(x.name)) { }

    Derived& operator=(Derived&& x)   // rvalues bind here
    {
        Base::operator=(std::move(x));
        vec  = std::move(x.vec);
        name = std::move(x.name);
        return *this;
    }
    // ...
};

移动构造函数Base(std::move(x))将x转换为右值引用,那么vec(std::move(x.vec))是如何操作的呢? x是否仍然存在?


1个回答

5
Base的移动构造函数原型应该是Base(Base&& b),因此在构造函数中调用Base(std::move(x))时,rvalue std::move(x)(类型为Derived)会被隐式转换为Base类型的rvalue。对于Base的移动构造函数来说,它看到了一个指向Base的rvalue引用,因此它将Base的成员从x中移出。x的其他成员还没有被移动,因此以下的移动初始化仍然有效。
移动构造和移动赋值不会使对象失效。对象的不变量在移动后仍应得到满足,以便其析构函数能够正常工作。

@bryantism,是的,基本移动构造函数只移动基类的成员。 - Brian Bi
@user1520427,不是的,你为什么会这样想呢? - Brian Bi
@BrianBi 因为它是 Derived 类型,所以肯定会解析为接受 Derived 类型的函数。然而,由 0x499602D2 链接的问题中的答案对此进行了澄清:“记住:std::move 实际上并没有移动任何东西。它只是一个 rvalue 强制转换,仅此而已。” - user1520427
@BrianBi 如果Base构造函数本身有Base(Base&& rhs)这样的实现,那么是否安全就要取决于具体的实现方式了? - bryantism
@bryantism,确实;如果没有的话,这段代码根本无法编译。请注意,即使您没有显式定义Base的移动构造函数,编译器可能会隐式地默认它(前提是您没有定义复制构造函数、复制赋值运算符、移动赋值运算符或析构函数)。 - Brian Bi
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接