2016-11-24 55 views
4

Efficient way to return a std::vector in c++有效的方式,通過值從功能

#include <cstdio> 
#include <vector> 
#include <chrono> 

std::vector<int> func1() { 
    std::vector<int> v; 
    v.reserve(1e6); 
    for (int i = 0; i < 1e6; i++) v.emplace_back(i); 
    return v; 
} 

std::vector<int> func2() { 
    std::vector<int> v; 
    v.reserve(1e6); 
    for (int i = 0; i < 1e6; i++) v.emplace_back(i); 
    return std::move(v); 
} 

int main() { 
    auto start1 = std::chrono::steady_clock::now(); 
    std::vector<int> v1 = func1(); 
    auto end1 = std::chrono::steady_clock::now(); 
    printf("%d\n", std::chrono::duration_cast<std::chrono::nanoseconds>(end1-start1).count()); 

    auto start2 = std::chrono::steady_clock::now(); 
    std::vector<int> v2 = func2(); 
    auto end2 = std::chrono::steady_clock::now(); 
    printf("%d\n", std::chrono::duration_cast<std::chrono::nanoseconds>(end2-start2).count()); 

/* 
    auto start3 = std::chrono::steady_clock::now(); 
    std::vector<int> v3 = v2; 
    auto end3 = std::chrono::steady_clock::now(); 
    printf("%d\n", std::chrono::duration_cast<std::chrono::nanoseconds>(end3-start3).count()); 
*/ 

    return 0; 
} 

在方法2返回STL向量這是排序的擴展問題,我明確地告訴我想移動,而不是複製矢量編譯器,但運行該代碼多次表明方法1實際上有時勝過方法2,並且即使方法2獲勝,也不是太多。

方法3始終是最好的。當我必須從函數返回時如何模擬方法3? (不,我不能按引用傳遞)

使用GCC 6.1.0

+0

a)防止甚至最微小的不必要的編譯器優化量。作爲編譯器,我會刪除例如。 v3,所以第三個是最快的並不是你想知道的。 – deviantfan

+0

請注意,您的基準測試存在缺陷:您還在計算向量中的插入時間,包括*重新分配*。 –

+0

編譯器也可以使用'func1'的運動,它不需要複製。 –

回答

9

方法1 - 您正在使用Named Return Value Optimization (NRVO)。實際上,這是最好的,因爲在優化的代碼中根本沒有構造任何臨時對象。如果編譯器無法創建NRVO,它將使用移動語義,與方法2相同。

方法2 - 您正在有效關閉NRVO,並強制移動目標std :: vector的構造函數。所以,這是不好的,方法1.

方法3 - 你實際上,在這裏複製矢量,這是迄今爲止 - 最糟糕的表現。但是,由於您在一次傳輸(一大塊內存,而不是多次安裝)中複製了矢量,因此您可以獲得最佳性能,但這在方法1或2中的用例中不可複製。

NRVO如何工作? 當你只有一個返回值時:在這種情況下這是std::vector<int> v,編譯器根本不在函數內部創建這個向量。它創建一個未命名的右值向量,您將返回,並將其引用傳遞給您的函數。

像這樣的事情將在優化代碼發生:

std::vector<int> func1(std::vector<int>& hidden) { 
    hidden.emplace_back(stuff); 
    return; 
} 
+0

我明白了。刪除評論。我同意。這個測試案例在這個工作臺上沒有任何業務,因爲它將蘋果與桔子進行比較。 – WhozCraig