插入从函数返回的std :: vector

时间:2014-11-20 14:11:54

标签: c++ vector

我发现自己经常做这样的事情来连接从函数返回的几个向量(可能是类函数):

#include <vector>
#include <iostream>
using namespace std;

vector<int> v1;

const vector<int>& F1() {
    cout << "F1 was called" << endl;
    /*Populate v1, which may be an expensive operation*/
    return v1;
}

int main() {
    vector<int> Concat;
    Concat.insert(Concat.end(), F1().begin(), F1().end());
    /*Do something with Concat*/
    return 0;
}

正如我所料,F1()被调用两次,如果这是一个昂贵的函数调用,这可能是不可取的。另一种方法是将F1()的返回值复制到一个临时向量中,该向量只需要一个函数调用,但是如果向量很大则会产生复制操作,这可能是不合需要的。我能想到的唯一另一种选择是创建一个指向临时向量的指针,并将F1()的返回值分配给它:

int main() {
    vector<int> Concat;
    const vector<int>* temp = &F1();
    Concat.insert(Concat.end(), temp->begin(), temp->end());
    /*Do something with Concat*/
    return 0;
}

这真的是最好的解决方案吗?使用临时变量似乎很麻烦,特别是如果我需要连接几个向量。我也觉得应该有一种方法来使用引用而不是指针来做到这一点。有什么建议吗?

3 个答案:

答案 0 :(得分:5)

最佳解决方案不是直接使用vector,而是OutputIteratorstd::back_inserter

template <typename OutputIterator>
OutputIterator F1( OutputIterator out )
{
    cout << "F1 was called" << endl;
    /* Insert stuff via *out++ = ...; */
    *out++ = 7;
    return out;
}

int main()
{
    std::vector<int> Concat;
    // perhaps reserve some moderate amount of storage to avoid reallocation

    F1( std::back_inserter(Concat) );
    F1( std::back_inserter(Concat) );
}

Demo。 这样就可以实现最高的效率和灵活性。

答案 1 :(得分:2)

  

这真的是最好的解决方案吗?

没有。 std::vector支持移动语义,所以你应该这样做:

vector<int> F1() // return by value
{
    std::vector<int> v1; // locally declared here
    cout << "F1 was called" << endl;
    /*Populate v1, which may be an expensive operation*/
    return v1;
}

int main() {
    vector<int> Concat;
    auto v2 = F1(); // create local variable and assign result of F1
    Concat.insert(Concat.end(), v2.begin(), v2.end());
    /*Do something with Concat*/
    return 0;
}

此代码:

  • 并不依赖于其他地方定义的全局变量
  • 效率很高(F1()被称为一次
  • 简单明了

编辑:第二个想法,请使用@ Columbo的方法。它更具惯用性,更灵活,更高效。

答案 2 :(得分:1)

vector<int> F1() {
    cout << "F1 was called" << endl;
    vector<int> v1;
    /*Populate v1, which may be an expensive operation*/
    return v1;
}

int main() {
    vector<int> Concat;
    vector<int> v1 = F1();
    Concat.insert(Concat.end(), v1.begin(), v2.end());
    /*Do something with Concat*/
    return 0;
}

这将比原始代码更快。 返回一个向量不应该在C ++ 11中复制它,你保证如果可移动,它将被移动。此外,在这种特殊情况下,NRVO(Namer返回值优化)将启动。

但是我会这样做:

void F1(vector<int>& v1) {
    cout << "F1 was called" << endl;
    /*Populate v1, which may be an expensive operation*/
    return;
}

你只是直接连接到方法中的v1。