Should I use C++11 emplace_back with pointers containers?

27,783

Solution 1

Pointers are scalar types and therefore literal types, and so copy, move and emplace construction (from an lvalue or rvalue) are all equivalent and will usually compile to identical code (a scalar copy). push_back is clearer that you're performing a scalar copy, whereas emplace_back should be reserved for emplace construction calling a non-copy- or move- constructor (e.g. a converting or multi-argument constructor).

If your vector should hold std::unique_ptr<Fruit> instead of raw pointers (to prevent memory leaks) then because you're calling a converting constructor emplace_back would be more correct. However that can still leak if extending the vector fails, so in that case you should use push_back(make_unique<Pear>()) etc.

Solution 2

Don't use raw pointers, use std::unique_ptr like this:

std::vector<std::unique_ptr<Fruit>> m_fruits;

And as you can't copy construct a std::unique_ptr you must use emplace_back (although you can use push_back with std::move).

m_fruits.emplace_back(new Pear());
m_fruits.emplace_back(new Tomato());

Edit:

As it appears that using std::vector<std::unique_ptr<T>>::emplace_back and new can leak if the std::vector needs and fails to reallocate memory, my recommended approach (until C++14 introduces std::make_unique) is to use push_back like this:

m_fruits.push_back(std::unique_ptr<Fruit>(new Pear()));
m_fruits.push_back(std::unique_ptr<Fruit>(new Tomato()));

Or using std::make_unique:

m_fruits.push_back(std::make_unique<Pear>());
m_fruits.push_back(std::make_unique<Tomato>());
Share:
27,783
Zhen
Author by

Zhen

I'm a Game Programmer at soul but currently I work as System Administrator. To see me rant: http://malcodigo.blogspot.com To see me walk: http://zhenpaseando.blospot.com To just see me: Napoli, Italia. My best known work: Doodle Hex for Nintendo DS, Cell &amp; Love for Android and Altamira II Supercomputer for the RES.

Updated on August 03, 2020

Comments

  • Zhen
    Zhen almost 4 years

    Having a usual Base -> Derived hierarchy, like:

    class Fruit { ... };
    class Pear : Fruit { ... };
    class Tomato : Fruit { ... };
    
    std::vector<Fruit*> m_fruits;
    

    Does it make sense (e.g: is performance better) to use emplace_back instead of push_back?

    std::vector::emplace_back( new Pear() );
    std::vector::emplace_back( new Tomato() );