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

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.


A c++0x perspective concerning test code of Yacobi's accepted answer:

  1. Add a move constructor to the class:

    Elem(Elem&& e) { std::cout << "Move\n"; }
    

    With gcc I get "Move" instead of "Copy" as output for push_back, which is far more efficient in general.

  2. Even slightly better with emplace operations (take the same arguments as the constructor):

    v.emplace_back()

Test Output:

1
Construct
Destruct

2
Construct
Copy
Destruct
Destruct

Tags:

C++

Stl

Vector