Search code examples
c++c++11container-data-type

How to choose between `push_*()` and `emplace_*()` functions?


I understand the difference between the two function variants.

My question is: should I normally use good old push_*() version and only switch to emplace_*() when my profiler tells me this will benefit performance (that is, do not optimise prematurely)? Or should I switch to using emplace_*() as the default (perhaps not to pessimise the code unnecessarily - similar to i++ vs ++i in for loops)?

Is any of the variants more universal than the other (that is, imposes less constraints on the type being inserted) in realistic non-contrived use cases?


Solution

  • While writing the code I would not worry about performance. Performance is for later when you already have code that you can profile.

    I'd rather worry about expressiveness of the code. Roughly speaking, push_back is for when you have an element and want to place a copy inside the container. emplace_back is to construct the element in place.

    Consider what has the lower "wtf-count":

    struct foo {int x;int y;};
    
    void foo_add(const foo& f,std::vector<foo>& v) {
        v.emplace_back(f);   // wtf ?!? we already have a foo
        v.push_back(f);      // ... simply make a copy (or move)
    }
    
    void foo_add(int x, int y, std::vector<foo>& v) {
        auto z = foo{x,y};      // wtf ?!? 
        f.push_back(z);         // why create a temporary?
        f.emplace_back(x,y);    // ... simply construct it in place
    }