Insert std :: vector as return from function

I often do something like this to concatenate multiple vectors returned from functions (possibly class functions):

#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;
}

As I expected, it F1()is called twice, which may be undesirable if this is an expensive function call. An alternative is to copy the return value F1()to a temporary vector, which will require only one function call, but will perform a copy operation, which may be undesirable if the vector is large. The only alternative I can imagine is to create a pointer to a temporary vector and assign it a return value F1()as follows:

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

? , . , , . ?

+4
3

- vector , OutputIterator std::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) );
}

. .

+5

?

. 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
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;
}

it will be even faster than the source code. Returning a vector should not copy it to C ++ 11, you are guaranteed that if it is moved, it will be moved. Moreover, in this particular case, NRVO (Namer Countdown Value Optimization) will start.

However, I would do it as follows:

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

and you just concatenate directly to v1 in the method.

+1
source

All Articles