Search code examples
c++backemplace

C++ Emplace Back vs Push Back Vector


I am trying to understand emplace_back vs. push_back in Vector C++. Though the whole process of both emplace_back and push_back is to append data at the end, From what I understand from emplace, it has no temporary objection creation. But When I see the logs, both behaviour remains the same, Need help in understanding emplace_back vs. push_back

#include <iostream>
#include <vector>

using namespace std;

struct Foo
{
    int myint;

    Foo(int n) 
    {
        cout << "constructor called " << this << endl;
        myint = n;
    }

    Foo(const Foo& rhs ) 
    {
        cout << "copy constructor called " << this << endl;
        myint = rhs.myint;
    }

    void display() {
        cout << "in Display Foo int = " << myint << endl;
    }

};


int main()
{
    cout<<"********emplace example start ********"<<endl;
    std::vector<Foo> v;

    //v.push_back(Foo(85));
    v.emplace_back(Foo(34));

    for(auto &it : v) 
    {
        it.display();
    }

    cout<<"********emplace example end ********"<<endl;
    return 0;
}
**o/p:** 
**with emplace_back**

********emplace example start ********
constructor called 0x7ffe5ae28c18
copy constructor called 0x55e02adff280
in Display Foo int = 34
********emplace example end ********
 
**with push_back**

********emplace example start ********
constructor called 0x7ffcb958eb68
copy constructor called 0x5611e5144280
in Display Foo int = 85
********emplace example end ********

Solution

  • emplace_back passes on the arguments given to it to the constructor of the element type to construct it in-place. This is what allows emplace_back to be used without creating a temporary object.

    You are not making use of that. You are still creating a temporary in v.emplace_back(Foo(34)); with the expression Foo(34). A reference to this Foo(34) temporary is then passed to the (copy) constructor of Foo to create the element in-place, but the temporary is already created outside the emplace_back call.

    Instead, pass on just the arguments to the constructor:

    v.emplace_back(34);
    

    Which will pass 34 to the constructor of Foo to construct it in-place without any temporary copy.