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?
Yes, std::vector<T>::push_back() creates a copy of the argument and stores it in the vector.
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.
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.
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.
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With