Foo(Foo&& other) {
this->bar = other.bar;
other.bar = nullptr;
}
Foo(Foo* other) {
this->bar = other->bar;
other->bar = nullptr;
}
以上兩個似乎只是在做同樣的事情。那麼爲什麼建議使用移動構造函數呢?它提供了什麼優勢?使用移動構造函數與傳遞指針有什麼優勢?
Foo(Foo&& other) {
this->bar = other.bar;
other.bar = nullptr;
}
Foo(Foo* other) {
this->bar = other->bar;
other->bar = nullptr;
}
以上兩個似乎只是在做同樣的事情。那麼爲什麼建議使用移動構造函數呢?它提供了什麼優勢?使用移動構造函數與傳遞指針有什麼優勢?
使用適當的轉移構造的原因有很多:
公約。請看下面的代碼:
Foo foo;
Foo bar(std::move(foo));
如果你看到代碼,它是豐富清楚你想要做什麼:你正在移動foo
爲bar
。相比之下:
Foo foo;
Foo bar(&foo);
這是什麼意思?它是否存儲指向另一個Foo
的指針?是Foo
某種鏈接列表節點類型?您必須在Foo
的基於指針的構造函數的文檔中查找它。
你不能得到一個指向prvalues的指針。 (pre-C++ 17)會創建一個臨時值,然後從它移動到bar
(此舉可能會在C++ 17之前被忽略)。但是你不能這樣做:Foo bar(&Foo{})
。
你可以從有意義的事物中自動移動。 C++ 17的廣義省音讓許多的這些舉動自動消失,但也有一些仍然存在:
Foo function()
{
Foo foo;
//Do stuff
return foo;
}
這將從foo
移動,而無需調用std::move
。原因是foo
是即將銷燬的局部變量。以這種方式返回意味着從它轉換到返回值是完全合理的。
你的方式需要明確寫入return &foo
。這使得返回類型扣除auto
變得相當困難。這樣的函數會推導出一個Foo*
,這意味着你剛剛返回了一個懸掛指針。而如果你做return foo;
,它會推導一個Foo
prvalue,並帶有一個自動移動(可能會被忽略)。
無需nullptr
檢查。如果你拿一個Foo*
,有人可能會傳遞一個空指針。而引用,這是不太可能的(他們已經調用UB)。
如果我們想移動與現有的語言結構的支持,我們會剛使用非const
引用意味着「移動」,而不是一個指針。通過賦予它自己的語法,在我們移動某個事物時以及當我們不移動時清楚地說明。
那麼,對於初學者來說,你不能採用右值的地址...... – Brian
優點是移動構造函數將在適用的移動/複製上下文中自動使用。你的「指針」構造函數不會。 – AnT
另外,引用不能爲空,但可以是一個指針,所以在交換之前你必須顯式檢查這個條件。 –