考慮下面的代碼中的一員:如何返回本地對象
struct Foo
{
Foo() { cout << "Foo()\n"; }
~Foo() { cout << "~Foo()\n"; }
Foo(Foo&) { cout << "Foo(Foo&)\n"; }
Foo(Foo&&) { cout << "Foo(Foo&&)\n"; }
int d;
};
struct Bar
{
Foo bigData;
void workOnBigData() { /*...*/ }
}
Foo getBigData()
{
Bar b;
b.workOnBigData();
return b.bigData;
}
什麼是落實getBigData()
在副本ellision方面/移動語義的最佳方式?在這個實現中,編譯器似乎不被允許移動bigData
。我測試了以下功能:
Foo f()
{
Foo foo;
return foo; // RVO
}
Foo g()
{
Bar b;
return b.bigData; // Copy
}
Foo h()
{
Bar b;
auto r = move(b.bigData);
return r; // Move
}
你能解釋這些實現的結果,並顯示返回本地對象的成員的最有效途徑。
對於命名返回值優化,調用者調用之前保留一些堆棧空間功能。這個內存然後將被用來*在*中構造被調用者的本地對象,return語句變成了no-op。因此,NRVO不能應用於子對象,只能用於完成對象(它有其他限制)。 – dyp
自動*返回*是一個優化,它改變了程序的可觀察行爲。它被保守地引入,即僅適用於NRVO被允許應用(但編譯器無法)和其他一些特殊情況的情況。如果沒有引入,那麼人們通常會寫'return std :: move(x);'即使''''可以通過NRVO返回;但'move(x)'防止NRVO,所以這將是一個悲觀(對於移動類型,如果應用NRVO,'return x''還必須檢查移動ctor)。 – dyp
@dyp是否意味着,每當NRVO無法應用時,應該使用return std :: move(x)來強制執行返回操作(在這種情況下不能自動完成)? – hansmaad