tags:

views:

547

answers:

8
+2  A: 

The second one, as long as you reserve the right capacity first.

One problem I see (apart from style) is that in the first one, if your copy assignment throws, you have taken an operation that should give you the strong guarantee, and used it to give no guarantee.

Greg Rogers
+1  A: 

So what's wrong with this?

out = in;

Don't you think that'd have the best possible behavior? If it doesn't, that sucks.

Also, your two code examples should be

out.resize( in.size() );
T1::iterator outIt = out.begin();
for( T1::iterator inIt = in.begin(); inIt != in.end(); ++inIt, ++outIt )
   *outIt = *inIt;

and

out.erase(out.begin(), out.end());
for( T1::iterator inIt = in.begin(); inIt != in.end(); ++inIt )
    out.push_back( *inIt );
Matt Cruikshank
Apologies but I simplified the example and used some pseudo code in the for loop
Patrick
+2  A: 

If you care about preserving in then do:

out = in;

If you don't, then do:

std::swap(out, in);

If out and in are different types of containers, then try this:

out.erase(out.begin(), out.end());
// if it's a vector or other contiguous memory container, you'll want to reserve first
// out.reserve(in.size());
std::copy(in.begin(), in.end(), back_inserter(out));
Eclipse
+1  A: 

If you are dealing with simple values like integers or doubles it will not matter (performance wise) if you resize and set or reserve and push_back.

If you are dealing with more complex objects that have a significant constructor it is better to use the second push_back based method.

If you objects do not have a meaningful default constructor then the push_back approach is the only technique that works.

James Dean
Good, clear answer. It's probably worth stressing that that reserve() isn't in the original question. That's the key to your answer.
Shmoopty
+3  A: 

The second, and if you're concerned about multiple extensions use out.reserve(). The right answer to adding to a vector is almost always push_back or back_inserter, which avoid some possible problems (exception guarantees, constructors, writing past the end, for example) that you'd have to pay attention to with other methods.

David Thornley
A: 

Something similar was discussed here before.

Arkadiy
+1  A: 

I had a situation where I got worse performance in push_back-based solution compared to one using the [] operator on a resized vector. The cause of the difference was the overhead in checking whether the vector needs to expand its capacity every time it was doing a push_back.

What made it even worse was that the compiler decided it couldn't inline the call to push_back, but it did inline the reserve-logic into the push_back method. This gave the overhead of a function call and the function invoked was unnecessary large. Even after some force_inline massage, it wasn't as fast as the loop based on the [] operator.

A loop based on iterators or the [] operator won't do anything but writing the value, at least not when working with simple types. If working with more advanced types, the cost of the default constructor when resizing the vector may ruin the potential wins.

Anyway, if your program spends most of its time in these kinds of loop I definitely think you should benchmark the different solutions and see if there are any performance to gain by using one of the solutions. If you are not spending considerable amount of your execution time in the function you described, you shouldn't care about this post :)

Laserallan
A: 

I prefer push_back over array assignment as push_back will work with or without randomaccessiterators. Array assignment requires them. If you force randomaccessiterators now you can't easily change the container in the future. Of course, to avoid resize issues you call vector::capacity instead of resize.

jmucchiello