函式返回大向量

Version >= C++ 11

在 C++ 11 中,編譯器需要隱式地從正在返回的區域性變數移動。此外,大多數編譯器可以在許多情況下執行複製省略並完全忽略移動。因此,返回可以便宜地移動的大型物體不再需要特殊處理:

#include <vector>
#include <iostream>

// If the compiler is unable to perform named return value optimization (NRVO)
// and elide the move altogether, it is required to move from v into the return value.
std::vector<int> fillVector(int a, int b) {
    std::vector<int> v;
    v.reserve(b-a+1);
    for (int i = a; i <= b; i++) {
        v.push_back(i);
    }
    return v; // implicit move
}

int main() { // declare and fill vector
    std::vector<int> vec = fillVector(1, 10);

    // print vector
    for (auto value : vec)
        std::cout << value << " "; // this will print "1 2 3 4 5 6 7 8 9 10 "

    std::cout << std::endl;

    return 0;
}

Version < C++ 11

在 C++ 11 之前,大多數編譯器已經允許並實現了 copy elision。但是,由於缺少移動語義,在遺留程式碼或程式碼中必須使用未實現此優化的較舊編譯器版本進行編譯,你可以找到作為輸出引數傳遞的向量以防止不需要的副本:

#include <vector>
#include <iostream>

// passing a std::vector by reference
void fillVectorFrom_By_Ref(int a, int b, std::vector<int> &v) {
    assert(v.empty());
    v.reserve(b-a+1);
    for (int i = a; i <= b; i++) {
        v.push_back(i);
    }
}

int main() {// declare vector
    std::vector<int> vec;
    
    // fill vector
    fillVectorFrom_By_Ref(1, 10, vec);
    // print vector
    for (std::vector<int>::const_iterator it = vec.begin(); it != vec.end(); ++it)
        std::cout << *it << " "; // this will print "1 2 3 4 5 6 7 8 9 10 "
    std::cout << std::endl;
    return 0;
}