我有一個工廠函數返回一個STL容器:效率基於函數返回
const std::vector<int> f(...) {
std::vector<int> retval;
return retval;
}
我想這是確定定義一個STL實例如下(沒有錯誤):
const std::vector<int> stl_instance(f(...));
但是這樣做效率高嗎?
是否將臨時stl對象直接分配給stl_instance
?
我有一個工廠函數返回一個STL容器:效率基於函數返回
const std::vector<int> f(...) {
std::vector<int> retval;
return retval;
}
我想這是確定定義一個STL實例如下(沒有錯誤):
const std::vector<int> stl_instance(f(...));
但是這樣做效率高嗎?
是否將臨時stl對象直接分配給stl_instance
?
返回const rvalue是C++ 11中的反模式。第一考慮返回非const右值:
std::vector<int> f(int n)
{
return std::vector<int>(n);
}
int main()
{
std::vector<int> v;
v = f(3);
}
在C++ 98/03,該代碼將去堆至少兩次:
如果你的編譯器不適用RVO,你會得到3個分配。
在C++ 11中,只有1個堆分配:在f
內部創建向量。無論RVO如何,都會發生這種情況。其原因是,所有的STL容器具有移動構造函數和移動賦值運算符具有簽名
vector(vector&& other);
vector& operator=(vector&& other);
右值引用&&
將資源從創建函數內部直接移動到目的地。然而,您的代碼簽名
const std::vector<int> f(int n)
{
return std::vector<int>(n);
}
將禁用移動語義,因爲一件T & &(即移動構造函數和賦值操作符的參數)將不綁定到一個const右值參數(即返回值你的功能)。這有效地使你的代碼運行在C++ 98/03下(即有2或3堆分配)。
這是罰款和法定代碼。
通過複製elision,編譯器將負責必要的優化(,如果它可以是)。
臨時f(...)
保證至少直到表達式結束。請注意,表達式在從stl_instance(f(...))
返回之後結束,具體來說是;
(在呼叫結束時的分號)。所以它是完全有效的。
C++ 03標準§12.2/ 3:
臨時對象被銷燬作爲評價全表達式(1.9),該(詞法)包含在其中創建它們的點的最後一步。
C++ 11移動語義應該改善前景以及是嗎? –
@KarthikT:的確如此。 –
@AlokSave它是合法的,但肯定不是很好的C++ 11代碼,因爲const返回值會禁用移動語義。 – TemplateRex