我对继承层次结构中的移动构造函数有疑问。在C++中的引物(斯坦利李普曼)中提到,在一个继承层次结构中的转移构造函数将像这样被定义:将继承层次结构中的构造函数移动
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 ::移动,同时调用由于基座移动的构造'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之后,对象的基础部分将处于有效状态,并且派生部分仍然处于有意义的状态。请帮我理解这一点。
如果我不在派生体中访问d,那么我将如何移动派生成员? – Madhusudhan
复制交换成语(我没有添加复制构造函数或赋值运算符):https://ideone.com/HpotCN它只是显示移动如何与分层类一起工作。移动不会“毁灭”对象,直到移动完成(或直到它超出范围)。它只是做一个有效的交换或其内部的透明副本。由于该对象实际上并未“移动”,因此仍然可以访问其尚未触及的其他成员。只有当移动完成时,另一个对象才会被销毁。至少我是这么看的。 – Brandon
@CantChooseUsernames - 我不明白你为什么使用std :: forward。我还没有遇到std :: forward,并且我正在阅读的这本书提到了std :: move在这里使用。对不起我的无知。我是一个初学者,逐一阅读各章。在你的代码中,如果我用std :: move替换std :: forward,那么swap(other,* this)仍然有效吗?我在问这个,因为这本书提到std :: move之后移动的对象不应该被使用。 – Madhusudhan