我怀疑与继承层次结构中的Move构造函数有关。在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 */}
};
在移动构造函数中,我尝试在调用基本移动构造函数时删除std :: move,因为' d'是一个右值参考。
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?
}
我确实理解Base类只会移动与基类相关的成员,并且不会触及派生类成员。但这是一个例外,在std :: move之后,对象的基本部分将处于有效的被破坏状态,并且派生部分仍然处于有意义的状态。请帮我理解这一点。
答案 0 :(得分:4)
class Base
{
// data members...
public:
Base(Base&& other) = default;
};
class Derived
{
// data members...
public:
Derived(Derived&& other) : Base(std::move(other)) { ... }
};
Derived
移动构造函数使用other
将std::move
强制转换为右值,然后将结果传递给Base
移动构造函数,该构造函数涉及{{1}的隐式转换转到Derived&&
。
Base&&
移动构造函数可能会窃取Base
的基类成员的内容,但它无法触及派生类成员的内容,因为它只能看到{{1} }}