Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

Efficient insertion

Move-aware containers
Emplace: Placement insertion

Move semantics and placement insertion are two features brought by C++11 containers that can have a very positive impact in your C++ applications. Boost.Container implements both techniques both for C++11 and C++03 compilers.

All containers offered by Boost.Container can store movable-only types and actual requirements for value_type depend on each container operations. Following C++11 requirements even for C++03 compilers, many operations now require movable or default constructible types instead of just copy constructible types.

Containers themselves are also movable, with no-throw guarantee if allocator or predicate (if present) copy operations are no-throw. This allows high performance operations when transferring data between vectors. Let's see an example:

#include <boost/container/vector.hpp>
#include <boost/move/move.hpp>
#include <cassert>

//Non-copyable class
class non_copyable
{
   BOOST_MOVABLE_BUT_NOT_COPYABLE(non_copyable)

   public:
   non_copyable(){}
   non_copyable(BOOST_RV_REF(non_copyable)) {}
   non_copyable& operator=(BOOST_RV_REF(non_copyable)) { return *this; }
};

int main ()
{
   using namespace boost::container;

   //Store non-copyable objects in a vector
   vector<non_copyable> v;
   non_copyable nc;
   v.push_back(boost::move(nc));
   assert(v.size() == 1);

   //Reserve no longer needs copy-constructible
   v.reserve(100);
   assert(v.capacity() >= 100);

   //This resize overload only needs movable and default constructible
   v.resize(200);
   assert(v.size() == 200);

   //Containers are also movable
   vector<non_copyable> v_other(boost::move(v));
   assert(v_other.size() == 200);
   assert(v.empty());

   return 0;
}

All containers offered by Boost.Container implement placement insertion, which means that objects can be built directly into the container from user arguments without creating any temporary object. For compilers without variadic templates support placement insertion is emulated up to a finite (10) number of arguments.

Expensive to move types are perfect candidates emplace functions and in case of node containers (list, set, ...) emplace allows storing non-movable and non-copyable types in containers! Let's see an example:

#include <boost/container/list.hpp>
#include <cassert>

//Non-copyable and non-movable class
class non_copy_movable
{
   non_copy_movable(const non_copy_movable &);
   non_copy_movable& operator=(const non_copy_movable &);

   public:
   non_copy_movable(int = 0) {}
};

int main ()
{
   using namespace boost::container;

   //Store non-copyable and non-movable objects in a list
   list<non_copy_movable> l;
   non_copy_movable ncm;

   //A new element will be built calling non_copy_movable(int) contructor
   l.emplace(l.begin(), 0);
   assert(l.size() == 1);

   //A new element will be built calling the default constructor
   l.emplace(l.begin());
   assert(l.size() == 2);
   return 0;
}


PrevUpHomeNext