[英]C++11 Move constructor optimization
我目前正試圖抓住移動構造函數。 我發現了以下內容(使用g++ d.cpp --std=c++11 -O3
編譯g++ d.cpp --std=c++11 -O3
)
class A {
string _x;
public:
A(string x) { cout << "default contrsutctor: " << x << "\n"; _x = x; }
A(const A& other) { cout << "copy contrsutctor: " << other._x << "\n"; _x = other._x; }
A(A&& other) { cout << "move contrsutctor: " << other._x << "\n"; _x = other._x; }
A foo() {
cout << "foo: " << _x << "\n";
return A("foo");
}
};
int main()
{
A a;
A b = a;
b.foo();
}
我希望這輸出:
default contrsutctor: a
move contrsutctor: a
foo: a
default contrsutctor: foo
但輸出是:
default contrsutctor: a
copy contrsutctor: a
foo: a
default contrsutctor: foo
為什么不使用移動構造函數優化A b = a
線? 之后永遠不會使用a對象,因此優化代碼以使用它而不是復制構造函數是安全的。
我知道我可以強制使用std::move()
來調用move構造函數,但是我希望在這樣的情況下自動執行此操作。
為什么不使用移動構造函數優化A b =一條線?
您可以在復制構造函數和移動構造函數中執行的操作可能完全不同。 編譯器無法保證兩個構造函數的結果相同。 實現這種優化有可能改變程序的行為,從而破壞了as-if規則 。
您需要使用std::move
將a
為A&&
:
#include <utility>
int main()
{
A a("a");
A b = std::move(a);
b.foo();
}
移動構造函數的正確實現應該是:
A(A&& other)
: _x(std::move(other._x))
{}
線A b = std::move(a);
, a
應該是“空的”。在這種情況下, 正如@TonyD在評論中指出的那樣, a._x
將為空。a._str
可能處於未指定但有效的狀態( 移動std:string的構造函數 )。 你應該使用a
該行后慎用。
A b = a;
總是調用復制構造函數,無論它是否可以調用移動構造函數。 此外,對象a
的生命周期在分配后繼續,即使它不再使用。
如果要使用移動構造函數,則必須將其顯式化:
A b = std::move(a);
請注意,這可能是危險的,作為a
仍然在移動后訪問。 如果您以后不小心使用它,可能會有未定義的行為。
想想為什么它應該自動發生。 在你給出的例子中,沒有必要,因為你可以使用a
代替b
。 在許多情況下,它會更有意義移動構造函數/賦值將自動使用,例如A a; a = foo();
A a; a = foo();
。
為什么不使用移動構造函數優化A b =一條線?
因為這會改變程序的可觀察行為。 除非在特定情況下(§12.8/ 31),否則不允許編譯器自由更改程序的可觀察行為(§1.9/ 1)。 這不是其中之一。 從構造函數中刪除副作用,編譯器可能會優化它們。 當然,如果刪除副作用,那么你將不會注意到編譯器是否優化了構造函數的調用(除非你檢查匯編或二進制輸出),但這就是重點。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.