我对继承层次结构中的Move构造函数有疑问。在C ++ Primer(Stanley Lippman)中,提到了继承层次结构中的move构造函数将定义如下:
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 */}
};
Run Code Online (Sandbox Code Playgroud)
在move构造函数中,我尝试在调用基本move构造函数时删除std :: move,因为'd'是一个右值引用。
D(D&& d): Base(d) {/*initializers for members of D */}
Run Code Online (Sandbox Code Playgroud)
但这最终调用了基类副本构造函数,而不是move构造函数。
为了理解为什么需要std :: move,我在这个论坛上进行了搜索以查看以前的讨论,并且发现了一些答复,这些答复说尽管d是右值引用,但在派生类的move构造函数中它仍然是左值。因此,我们需要在其上调用std :: move,以确保调用了基类move构造函数。我了解这部分。
但是从C ++ Primer中,我了解到一旦调用了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?
}
Run Code Online (Sandbox Code Playgroud)
我确实知道,基类只会移动与基类相关的成员,而派生类成员将不会受到影响。但这是一个例外,在std :: move之后,对象的基础部分将处于有效的可破坏状态,而派生部分仍将处于有意义的状态。请帮助我理解这一点。
class Base
{
// data members...
public:
Base(Base&& other) = default;
};
class Derived
{
// data members...
public:
Derived(Derived&& other) : Base(std::move(other)) { ... }
};
Run Code Online (Sandbox Code Playgroud)
的Derived
移动构造函数投射other
到使用一个rvalue std::move
,然后将结果传递给所述Base
移动构造函数,它涉及到隐式转换从Derived&&
到Base&&
。
该Base
举措可以在构造窃取的基类成员的胆量other
,但不能触及派生类成员的胆量,因为它只看到了Base&&
。