Question: can emplace_back always be used where push_back can be used? If yes, given that emplace_back is supposedly more efficient, why not remove push_back, or alias push_back to emplace_back?
Yes, emplace_back
can always be used in place of push_back
because emplace_back
can perform everything that push_back
does and more. However, there are important distinctions between the two, and reasons for keeping both in the C++ Standard Library.
push_back
and emplace_back
push_back
:push_back
moves or copies it into the container.Usage:
cpp
std::vector<std::string> vec;
std::string s = "Hello";
vec.push_back(s); // Copy s into vec
vec.push_back("World"); // Move from temporary "World" into vec
emplace_back
:
cpp
std::vector<std::string> vec;
vec.emplace_back("Hello"); // Directly constructs the string "Hello" in-place
emplace_back
more efficient?emplace_back
avoids the overhead of constructing a temporary object and then copying/moving it into the container. By constructing the object directly within the container's memory, it can eliminate unnecessary allocations or operations. For example:
- With push_back
, you might create a temporary object, which is then moved or copied into the container.
- With emplace_back
, the object is constructed directly within the container, saving both the construction of a temporary and the move/copy operation.
push_back
or Alias It to emplace_back
?Despite emplace_back
being more flexible and often more efficient, there are several reasons for keeping both push_back
and emplace_back
:
push_back
is simpler to use when the object is already constructed. It's straightforward and conveys the intent clearly: "I want to insert this existing object into the container." For basic types (like int
, float
, or simple objects), the performance difference is negligible.emplace_back
, on the other hand, implies construction of a new object within the container. This additional functionality may be unnecessary when the object is already constructed.
Avoiding Misuse of emplace_back
:
Using emplace_back
might encourage users to pass constructor arguments unnecessarily when simply passing a fully constructed object with push_back
is clearer. For example, emplace_back
forwards constructor arguments, which can lead to confusion if not used carefully:
cpp
std::vector<std::string> vec;
std::string s = "Hello";
vec.emplace_back(s); // Constructs a string by copying 's', which is unnecessary here
Backward Compatibility:
push_back
has been part of C++ since the early days. Removing it or aliasing it would break a lot of existing code that relies on its well-defined behavior. Aliasing push_back
to emplace_back
could also introduce subtle issues, especially when working with types that have complex constructors.
Intent:
push_back
: "I want to append this fully constructed object."emplace_back
: "I want to construct an object in-place using these arguments."emplace_back
can technically be used everywhere, it doesn’t necessarily improve clarity in simple cases.While emplace_back
is more powerful and often more efficient than push_back
, especially for complex objects, both have their place in C++. The explicitness of push_back
for appending already constructed objects improves readability, while emplace_back
is valuable for in-place construction without unnecessary copies or moves. Hence, both are retained to serve distinct purposes in terms of clarity, intent, and backward compatibility.