我對繼承層次結構中的移動構造函數有疑問。在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