Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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() ); 
like image 240
Zhen Avatar asked Apr 03 '13 09:04

Zhen


People also ask

When should I use Emplace_back?

Specific use case for emplace_back : If you need to create a temporary object which will then be pushed into a container, use emplace_back instead of push_back . It will create the object in-place within the container.

Should I use Emplace_back or Push_back?

You should definitely use emplace_back when you need its particular set of skills — for example, emplace_back is your only option when dealing with a deque<mutex> or other non-movable type — but push_back is the appropriate default. One reason is that emplace_back is more work for the compiler.

Does Emplace_back increase container size by 1?

Description. The C++ function std::vector::emplace_back() inserts new element at the end of vector. Reallocation happens if there is need of more space. This method increases container size by one.

Does Emplace_back use move constructor?

Calling emplace_back will call the move constructor of std::string when std::move is used, which could save on a copy (so long as that string isn't stored in a SSO buffer). Note that this is essentially the same as push_back in this case.


1 Answers

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>()); 
like image 153
Felix Glas Avatar answered Sep 30 '22 01:09

Felix Glas