PaulH
PaulH

Reputation: 7853

Does returning a standard container incur a copy of the contents of the container?

If I have a function that returns an STL container am I incurring a copy of the entire contents of the standard container?

e.g. Is this:

void Foo( std::vector< std::string >* string_list );

better than this:

std::vector< std::string > Foo();

Does it matter what's in the container? For instance would returning a container like this:

struct buzz {
    int a;
    char b;
    float c;
}

std::map< int, buzz > Foo();

be a more costly operation than this:

std::map< int, int > Foo();

Thanks, PaulH


Edit: This is with C++03. A C++0x solution is, unfortunately, not acceptable.

Edit2: I am using the Microsoft Visual Studio 2008 compiler.

Upvotes: 4

Views: 1176

Answers (5)

ak.
ak.

Reputation: 3449

I wasn't 100% sure, but NO (thanks to the commentators) :

#include <vector>
#include <iostream>

#define LOCAL_FUN

struct A {
    A() { std::cout << "default ctor" << std::endl; }
    A(const A &a) { std::cout << "copy ctor" << std::endl; }
};

#ifdef LOCAL_FUN
std::vector<A> *pVec = NULL;
#endif

std::vector<A> func()
{
    std::vector<A> vec;
#ifdef LOCAL_FUN
    pVec = &vec;
#endif
    vec.push_back(A());
    std::cout << "returning" << std::endl;
    return vec;
}

int main(int argc, char *argv[])
{
    std::vector<A> ret = func();
#ifdef LOCAL_FUN
    if (pVec) {
        std::cout << pVec->size();
    }
#endif
}

output (with LOCAL_FUN):

default ctor
copy ctor
returning
1

Edit: Some more playing with the code led me to some fun with the local variables (LOCAL_FUN). So a really bad compiler that does not optimize copying, can actually break this code...

Upvotes: 3

mihir
mihir

Reputation: 1

It depends on the copy constructor of the container. C++ has pass by value semantics. So when you return a vector for function Foo() it will be returned using value semantics i.e. a copy constructor will be invoked to copy the value of the vector. In this case the copy constructor of std::vector creates a new container and copies the values. In case of passing a pointer to the container you would have to allocate the memory if you have not allocated it already so the pointer points to an actual container and not a null value. From a programming practice perspective this is not a good thing to do because you leave the semantics open to interpretation. Better idea would be to pass a reference to the container and let the function fill the container with the desired elements.

Upvotes: 0

Gene Bushuyev
Gene Bushuyev

Reputation: 5538

First compiler is required to elide copy construction, if can't, then move, if can't then copy. So if you have a really bad compiler, you risk incurring an overhead of an extra copy. See this discussion for details.

Upvotes: 0

Šimon T&#243;th
Šimon T&#243;th

Reputation: 36433

Yes it will involve a copy of the container, but don't use void Foo( std::vector< std::string >* string_list );. Use void foo( vector<string>& string_list); instead.

Or just switch to C++0x and use a compiler that has already move optimizations implemented in the library.

Upvotes: 2

fredoverflow
fredoverflow

Reputation: 263118

C++03 will probably do (named) return value optimization (google RVO and NRVO).

If that optimization is not applicable, C++0x will do move semantics.

Upvotes: 6

Related Questions