I\'m a bit confused regarding the difference between push_back
and emplace_back
.
void emplace_back(Type&& _Val);
void push_
emplace_back
shouldn't take an argument of type vector::value_type
, but instead variadic arguments that are forwarded to the constructor of the appended item.
template <class... Args> void emplace_back(Args&&... args);
It is possible to pass a value_type
which will be forwarded to the copy constructor.
Because it forwards the arguments, this means that if you don't have rvalue, this still means that the container will store a "copied" copy, not a moved copy.
std::vector<std::string> vec;
vec.emplace_back(std::string("Hello")); // moves
std::string s;
vec.emplace_back(s); //copies
But the above should be identical to what push_back
does. It is probably rather meant for use cases like:
std::vector<std::pair<std::string, std::string> > vec;
vec.emplace_back(std::string("Hello"), std::string("world"));
// should end up invoking this constructor:
//template<class U, class V> pair(U&& x, V&& y);
//without making any copies of the strings
emplace_back
conforming implementation will forward arguments to the vector<Object>::value_type
constructor when added to the vector. I recall Visual Studio didn't support variadic templates, but with variadic templates will be supported in Visual Studio 2013 RC, so I guess a conforming signature will be added.
With emplace_back
, if you forward the arguments directly to vector<Object>::value_type
constructor, you don't need a type to be movable or copyable for emplace_back
function, strictly speaking. In the vector<NonCopyableNonMovableObject>
case, this is not useful, since vector<Object>::value_type
needs a copyable or movable type to grow.
But note that this could be useful for std::map<Key, NonCopyableNonMovableObject>
, since once you allocate an entry in the map, it doesn't need to be moved or copied ever anymore, unlike with vector
, meaning that you can use std::map
effectively with a mapped type that is neither copyable nor movable.
A nice code for the push_back and emplace_back is shown here.
http://en.cppreference.com/w/cpp/container/vector/emplace_back
You can see the move operation on push_back and not on 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.
Notes:
push_back
in the above case will create a temporary object and move it
into the container. However, in-place construction used for emplace_back
would be more
performant than constructing and then moving the object (which generally involves some copying).emplace_back
instead of push_back
in all the cases without much issue. (See exceptions)One more in case of lists:
// constructs the elements in place.
emplace_back("element");
//It will create new object and then copy(or move) its value of arguments.
push_back(explicitDataType{"element"});
Optimization for emplace_back
can be demonstrated in next example.
For emplace_back
constructor A (int x_arg)
will be called. And for
push_back
A (int x_arg)
is called first and move A (A &&rhs)
is called afterwards.
Of course, the constructor has to be marked as explicit
, but for current example is good to remove explicitness.
#include <iostream>
#include <vector>
class A
{
public:
A (int x_arg) : x (x_arg) { std::cout << "A (x_arg)\n"; }
A () { x = 0; std::cout << "A ()\n"; }
A (const A &rhs) noexcept { x = rhs.x; std::cout << "A (A &)\n"; }
A (A &&rhs) noexcept { x = rhs.x; std::cout << "A (A &&)\n"; }
private:
int x;
};
int main ()
{
{
std::vector<A> a;
std::cout << "call emplace_back:\n";
a.emplace_back (0);
}
{
std::vector<A> a;
std::cout << "call push_back:\n";
a.push_back (1);
}
return 0;
}
output:
call emplace_back:
A (x_arg)
call push_back:
A (x_arg)
A (A &&)