Move constructors are often cheaper than copy constructors, which makes the construction and immediate relocation of objects in modern C++ more effective than in C++03. However, just moving the parts needed to construct the object in the right place can be even more effective. Several standard library functionalities use perfect forwarding to construct objects right where they are needed.

Example

From copy to move

Let’s consider this little C++03 code snippet:

typedef std::vector<int> Numbers; std::vector<Numbers> numbersContainer; numbersContainer.reserve(1); int newNumbers[] = {1, 1, 2, 3, 5}; numbersContainer.push_back( Numbers(newNumbers, newNumbers + sizeof(newNumbers)/sizeof(newNumbers[0])) );

What we are doing here is inserting a new std::vector<int> with the content of the array at the end of numbersContainer . The vector is initialized with the content of the array newNumbers . Without too much detail, the execution steps for the last line will be roughly the following:

Construct a temporary `std::vector<int>` (aka. `Numbers`) from two pointers Copy construct a new object from the original constructed in step 1 at the end of `numbersContainer`’s storage: Allocate memory for the copied content Set the internal members accordingly (pointer to memory, capacity) Copy the content and set the internal member for the size accordingly Adjust the member for the size of `numbersContainer` Destroy the temporary, including a deallocation

Before I go into the details, here is the same code, polished for C++11:

using Numbers = std::vector<int>; std::vector<Numbers> numbersContainer; numbersContainer.reserve(1); auto newNumbers = std::array<int, 5>{1, 1, 2, 3, 5}; numbersContainer.push_back( Numbers(std::begin(newNumbers), std::end(newNumbers)) );

We are using a type alias here which is the modern equivalent to the typedef . In this case it’s essentially the same, but more convenient, as it defines the type in the same order we are used from other definitions in C++. The other change is the use of std::array instead of a plain C array and std::begin()/end() instead of manual pointer calculations. The crucial point however is that push_back now has an overload taking an rvalue reference, so it can move the temporary instead of copying it. Here are the execution steps:

Construct a temporary `std::vector<int>` (aka. `Numbers`) from the two iterators/pointers Move construct a new object from the original constructed in step 1 at the end of `numbersContainer`’s storage: Copy the internal members of the temporary, “stealing the guts” Set at least the internal data member of the temporary to 0 Adjust the member for the size of `numbersContainer` Destroy the empty temporary, which does nothing

Step 1 is equivalent to the C++03 version – std::array iterators are plain pointers. Step 3 is the same for both cases, it’s only cheap bookkeeping. Step 2 and 4 are the interesting difference: The allocation and following deallocation does not take place, because we moved the temporary.

We can do better: in-place construction

Let’s analyze if we could do better – at least in theory. We can’t get around the construction of a vector<int> , because that’s what is stored in numbersContainer . We can’t get rid of step 3 either, because the invariants of numbersContainer demand the bookkeeping. Step 4 does nothing, so what remains is step 2, the move construction.

In this case that does not look like much: copy three pointers or integrals (data pointer, size, capacity), set another one to 0. However, move constructors need not be that cheap. Objects that store their data on the heap can just swap a few pointers like std::vector does, but data stored in the object itself can not be moved, it has to be copied.

So, wouldn’t it be nice if we could get rid of the temporary and the move construction as well? As a matter of fact, since C++11 std::vector has a method emplace_back that takes an arbitrary number of arguments and uses perfect forwarding to construct the new object right in place:

using Numbers = std::vector<int>; std::vector<Numbers> numbersContainer; numbersContainer.reserve(1); auto newNumbers = std::array<int, 5>{1, 1, 2, 3, 5}; numbersContainer.emplace_back( std::begin(newNumbers), std::end(newNumbers) );

Without further ado, here’s what happens:

Perfectly forward any arguments … … to normally construct the new object at the end of `numbersContainer`’s storage Adjust the member for the size of `numbersContainer`

That’s it. Step 2 is the exact same constructor call we had for the temporary before, the one we can’t get around. Step 3 is the bookkeeping we’ll always have. The perfect forwarding is very easily optimized away by the compiler. There’s no unnecessary overhead left.

There are lots of functions like this in the standard library: of course there is emplace_front as well. Whenever a container has a insert method, there is a corresponding emplace method. std::make_shared and std::make_unique perfectly forward to achieve in-place construction.

Consider to use emplace functions to achieve in-place construction instead of moves or copies.

Readability