Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does vector::push_back and emplace_back call value_type::constructor twice?

Tags:

c++

c++11

I have this class:

class Foo {
public:
    Foo() {}
    Foo(const Foo&){cout << "constructed by lvalue reference." <<endl; }
    Foo(Foo&& ) {cout << "constructed by rvalue reference." << endl; }
};

then I insert into a vector:

Foo foo{};
vf.push_back(foo);

The output is surprising:

constructed by lvalue reference.
constructed by lvalue reference.

I assume it got copied when passing parameters, so I tried:

vf.push_back(move(foo));

and

vf.push_back(forward<Foo>(foo));

The output are slightly different due to move semantics but still calling constructor twice:

constructed by rvalue reference.
constructed by lvalue reference.

Why the constructors got called twice? How much performance does it impact? How can I avoid this?


I am using mingw-gcc-4.7.1 on Windows Vista

Total example:

#include <iostream>
#include <vector>

using namespace std;

class Foo {
public:
    Foo() {}
    Foo(const Foo&){cout << "constructed by lvalue reference." <<endl; }
    Foo(Foo&& ) {cout << "constructed by rvalue reference." << endl; }
};


int main(int argc, char **argv, char** envp)
{
    vector<Foo> vf;
    cout << "Insert a temporary." << endl;
    vf.emplace_back(Foo{});

    Foo foo{};
    cout << "Insert a variable." << endl;
    vf.emplace_back(foo);

    return 0;
}

Exact output:

Insert a temporary.
constructed by rvalue reference.
Insert a variable.
constructed by lvalue reference.
constructed by lvalue reference.
like image 756
SwiftMango Avatar asked Aug 15 '13 19:08

SwiftMango


1 Answers

When you insert new items in a vector the vector may have to allocate more memory to fit those objects. When that happens it needs to copy all it's elements to the new memory location. That will invoke the copy constructor. So when you insert your element you're getting the constructor for that new element and the constructor when copying the previous element.

like image 111
Dennis Persson Avatar answered Sep 21 '22 16:09

Dennis Persson