继承层次结构中的移动构造函数

14

我对继承层次结构中的移动构造函数有疑问。在C++ Primer(Stanley Lippman)中提到,继承层次结构中的移动构造函数应该定义如下:

class Base { /* Default Copy control and move constructor */ };

class D : public Base {
public:
  D(const D& d) : Base(d) {/*initializers for members of D */} //This is ok
  D(D&& d): Base(std::move(d)) {/*initializers for members of D */}
};

在移动构造函数中,由于 'd' 是右值引用,我尝试在调用基类移动构造函数时去掉 std::move。

 D(D&& d): Base(d) {/*initializers for members of D */}  

但实际上这调用了基类的复制构造函数,而不是移动构造函数。

为了理解为什么需要使用std::move,我搜索了这个论坛以查看之前的讨论,发现一些回复说,虽然'd'是右值引用,但在派生类的移动构造函数中它仍然是左值。因此,我们需要对它调用std::move,以确保调用基类的移动构造函数。我理解了这一点。

但根据C++ Primer的说明,一旦调用了std::move,我们就不应该再使用该对象。在std::move被调用的表达式结束后,对象将保持有效状态以进行破坏,但它持有的值可能没有意义。

那么,当我们回到派生类的移动构造函数体时,调用std::move以委托给基类的移动构造函数后,对象如何保持有意义的状态呢?

换句话说:

D(D&& d): Base(std::move(d)) {
  // Would 'd' be in a meaningful state here?
  // After std::move(d), can I still use 'd' here?
}

我确实理解基类只会移动与基类相关的成员,而派生类成员不会受到影响。但这是一个例外吗?在使用std::move后,对象的基础部分将处于可以被销毁的有效状态,而派生部分仍将处于有意义的状态。请帮助我理解这个问题。


如果我在派生类的主体中不访问d,那么我如何移动派生成员? - MS Srikkanth
复制交换惯用语(我没有添加复制构造函数或赋值运算符):https://ideone.com/HpotCN。它只是为了展示移动如何与分层类一起工作。移动在完成移动(或超出范围)之前不会“销毁”对象。它只是对其内部进行高效的交换或透明的复制。由于对象实际上并没有“移动”,因此您仍然可以访问尚未触及的其他成员。只有当移动完成时,另一个对象才被视为准备好销毁。至少这就是我看到的。 - Brandon
@CantChooseUsernames - 我不明白为什么你要使用std::forward。我还没有接触过std::forward,我正在阅读的书中提到应该在这里使用std::move。对于我的无知表示抱歉,我是一个按章节逐步进行的初学者。如果我用std::move替换std::forward,那么swap(other, *this)是否仍然有效?我之所以问这个问题是因为这本书提到,在std::move之后,移动的对象不应再被使用。 - MS Srikkanth
是的,它仍然有效。std::movestd::forward都只是转换。它也可以使用移动:https://ideone.com/HCNLST。其中一个只是用于完美转发并提供更多控制。是的,您可以访问未被基类的移动构造函数触及的对象部分。 - Brandon
@CantChooseUsernames - 谢谢。 - MS Srikkanth
1个回答

14
class Base
{
    // data members...
public:
    Base(Base&& other) = default;
};

class Derived
{
    // data members...
public:
    Derived(Derived&& other) : Base(std::move(other)) { ... }
};

Derived 移动构造函数使用 std::moveother 转换为右值,然后将结果传递给 Base 移动构造函数,其中涉及从 Derived&& 隐式转换为 Base&&

Base 移动构造函数可能会窃取 other 的基类成员对象,但它无法访问派生类成员对象,因为它只看到一个 Base&&


基类构造函数可以在 other 上调用虚函数,从而可以修改 Derived 将看到的内容。 - OwnageIsMagic
非常干净的回答@oktalist,谢谢! - user6547518

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