Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 819
Krzysiek Karbowiak Avatar asked Mar 02 '23 21:03

Krzysiek Karbowiak


1 Answers

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
} 
like image 70
463035818_is_not_a_number Avatar answered Mar 05 '23 16:03

463035818_is_not_a_number