Reputation: 7853
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
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
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
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
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
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