![](/img/trans.png)
[英]C++ template member initialization: move-construction with rvalue but reference with lvalue
[英]Hidden move-construction
為什么有時候不會移動構造函數調用? 測試move-semantics (實時代碼) :
struct Test {
int id;
Test(int id) : id(id) {
cout << id << " Test() " << endl;
}
~Test() {
cout << id << " ~Test() " << endl;
}
Test(const Test &t) : id(t.id) {
cout << id << " Test(const Test &t) " << endl;
}
Test(Test &&t) : id(t.id) {
cout << id << " Test(Test &&t) " << endl;
}
Test &operator=(const Test &t) {
cout << id << " operator=(const Test &t) " << endl;
return *this;
}
Test &operator=(Test &&t) {
cout << id << " operator=(Test &&t) " << endl;
return *this;
}
};
void f(Test z) {
cout << z.id << " f(Test z) " << endl;
}
int main() {
f(Test(1));
Test t(2); f(t);
}
輸出:
1 Test()
1 f(Test t) <---// where is move constructor ?!
1 ~Test()
2 Test()
2 Test(const Test &t) <---// copy constructor of t(2)
2 f(Test t)
2 ~Test()
2 ~Test()
測試顯示復制構造函數被調用。
但是,在f(Test(1));
之后f(Test(1));
調用函數f
而不為Test(1)
rvalue對象調用move-constructor。
它是隱式編譯器優化嗎? 或者我錯過了重要的一點?
明確允許編譯器忽略臨時對象的復制(或移動)。 基本上,對象是在預期有效結果的地方構建的。 如果構造函數或析構函數具有副作用,則甚至允許使用此省略。
相關條款是12.8 [class.copy]第31段:
當滿足某些條件時,允許實現省略類對象的復制/移動構造,即使為復制/移動操作選擇的構造函數和/或對象的析構函數具有副作用。 在這種情況下,實現將省略的復制/移動操作的源和目標視為僅僅兩種不同的引用同一對象的方式,並且該對象的銷毀發生在兩個對象的后期時間。沒有優化就被破壞了。 在下列情況下允許復制/移動操作(稱為復制省略)的這種省略(可以組合以消除多個副本):...
基本上可以使用復制省略的情況
return
語句時返回臨時變量或局部變量。 throw
表達式時拋出臨時變量或局部變量。 可以省略副本的確切條件列於12.8 [class.copy]第31段。
防止復制/移動省略的最簡單方法是將其傳遞給返回合適引用的函數,例如,使用
f(std::move(Test(1)));
應該防止移動省略。
完成此討論。 我們可以通過此選項在gcc中禁用此優化(復制省略):
-fno-elide-constructors
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.