Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

resize versus push_back in std::vector : does it avoid an unnecessary copy assignment?

Tags:

When invoking the method push_back from std::vector, its size is incremented by one, implying in the creation of a new instance, and then the parameter you pass will be copied into this recently created element, right? Example:

myVector.push_back(MyVectorElement()); 

Well then, if I want to increase the size of the vector with an element simply using its default values, wouldn't it be better to use the resize method instead? I mean like this:

myVector.resize(myVector.size() + 1); 

As far as I can see, this would accomplish exactly the same thing but would avoid the totally unnecessary assignment copy of the attributes of the element.

Is this reasoning correct or am I missing something?

like image 318
Chuim Avatar asked Dec 14 '09 19:12

Chuim


People also ask

Does std::vector Push_back make a copy?

Yes, std::vector<T>::push_back() creates a copy of the argument and stores it in the vector.

What happens when vectors are resized?

The C++ function std::vector::resize() changes the size of vector. If n is smaller than current size then extra elements are destroyed. If n is greater than current container size then new elements are inserted at the end of vector.

Should I use Emplace_back or Push_back?

You should definitely use emplace_back when you need its particular set of skills — for example, emplace_back is your only option when dealing with a deque<mutex> or other non-movable type — but push_back is the appropriate default. One reason is that emplace_back is more work for the compiler.

Is all data stored in a vector lost when resized?

Resizing a vector doesn't destroy the values stored in the vector (except for those beyond the new size when shrinking, of course), however growing a vector beyond its capacity will copy (or, in C++11, move) them to a new place, thus invalidating and iterators, pointers or references to those elements.


2 Answers

At least with GCC, it doesn't matter which you use (Results below). However, if you get to the point where you are having to worry about it, you should be using pointers or (even better) some form of smart pointers.. I would of course recommend the ones in the boost library.

If you wanted to know which was better to use in practice, I would suggest either push_back or reserve as resize will resize the vector every time it is called unless it is the same size as the requested size. push_back and reserve will only resize the vector if needed. This is a good thing as if you want to resize the vector to size+1, it may already be at size+20, so calling resize would not provide any benefit.

Test Code

#include <iostream> #include <vector>  class Elem{     public:         Elem(){             std::cout << "Construct\n";         }         Elem(const Elem& e){             std::cout << "Copy\n";         }         ~Elem(){             std::cout << "Destruct\n";         }    };   int main(int argc, char* argv[]){     {         std::cout << "1\n";         std::vector<Elem> v;         v.push_back(Elem());     }      {         std::cout << "\n2\n";         std::vector<Elem> v;         v.resize(v.size()+1);     } } 

Test Output

1 Construct Copy Destruct Destruct  2 Construct Copy Destruct Destruct 
like image 110
Yacoby Avatar answered Dec 19 '22 06:12

Yacoby


I find myVector.push_back(MyVectorElement()); much more direct and easier to read.

The thing is, resize doesn't just resize the array and default-construct elements on those places; that's just what it defaults to. It actually takes a second parameter which is what each new element will be made a copy of, and this defaults to T(). In essence, your two code samples are exactly the same.

like image 36
GManNickG Avatar answered Dec 19 '22 05:12

GManNickG