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

Move constructors in inheritance hierarchy

本文关键字:移动 构造函数 层次结构 继承      更新时间:2023-10-16

我对继承层次结构中的Move构造函数有疑问。在C++初级读本(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 */}
};

在move构造函数中,我在调用基move构造函数时尝试删除std::move,因为"d"是一个右值引用。

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

但这最终调用了基类复制构造函数,而不是移动构造函数。

为了理解为什么需要std::move,我在这个论坛上搜索了以前的讨论,发现了一些回复,其中说虽然"d"是一个右值引用,但在派生类的move构造函数中,它仍然是一个左值。因此,我们需要调用std::move来确保基类move构造函数被调用。我理解这部分。

但从C++初级读本中,我了解到一旦调用std::move,我们就不应该在调用之后使用该对象。在调用std::move的表达式结束后,对象将保持有效状态以进行销毁,但它所包含的值可能没有意义。

因此,当我们调用std::move来委托基类的move构造函数时,当我们回到派生类的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之后,对象的基础部分将处于有效的待销毁状态,而派生部分仍处于有意义的状态。请帮我理解这一点。

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&&