4

我有一個工廠函數返回一個STL容器:效率基於函數返回

const std::vector<int> f(...) { 
    std::vector<int> retval; 
    return retval; 
} 

我想這是確定定義一個STL實例如下(沒有錯誤):

const std::vector<int> stl_instance(f(...)); 

但是這樣做效率高嗎?

是否將臨時stl對象直接分配給stl_instance

回答

5

返回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,該代碼將去堆至少兩次:

  1. 要創建的F內的矢量(如果RVO適用)
  2. 從F公司迴歸到v分配。

如果你的編譯器不適用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堆分配)。

1

這是罰款和法定代碼。
通過複製elision,編譯器將負責必要的優化(,如果它可以是)。

臨時f(...)保證至少直到表達式結束。請注意,表達式在從stl_instance(f(...))返回之後結束,具體來說是;在呼叫結束時的分號)。所以它是完全有效的。

C++ 03標準§12.2/ 3:

臨時對象被銷燬作爲評價全表達式(1.9),該(詞法)包含在其中創建它們的點的最後一步。

+2

C++ 11移動語義應該改善前景以及是嗎? –

+0

@KarthikT:的確如此。 –

+2

@AlokSave它是合法的,但肯定不是很好的C++ 11代碼,因爲const返回值會禁用移動語義。 – TemplateRex