Sometimes, emplace_back
is more efficient and less verbose than push_back
. It is expected to be faster when the object is
constructed into the container instead of being constructed and assigned. This also happens when the pushed object has a different type from the one
held by the container.
This rule supports standard sequence containers: std::vector
, std::list
, std::deque
,
std::forward_list
, std::stack
, std::queue
and std::priority_queue
.
The rule raises an issue when an insertion function on a supported container leads to constructing a large temporary object that can be avoided
using the provided emplacement member function.
Noncompliant code example
class Circle { // Large object
std::string s;
int x;
int y;
int radius;
public:
Circle(int x, int y, int radius);
}
void f() {
std::vector<std::pair<int, std::string>> vec1;
std::string s;
vec1.push_back(std::make_pair(21, s)); // Noncompliant
std::vector<std::string> vec2;
vec2.push_back("randomStr"); // Noncompliant, conversion from char const * to string
std::vector<Circle> circles;
circles.push_back(Circle{2, 42, 10}); // Noncompliant
}
Compliant solution
class Circle { // Large object
std::string s;
int x;
int y;
int radius;
public:
Circle(int x, int y, int radius);
}
void f() {
std::vector<std::pair<int, std::string>> vec1;
std::string s;
vec1.emplace_back(21, s); // Compliant
std::vector<std::string> vec2;
vec2.emplace_back("randomStr"); // Compliant
std::vector<Circle> circles;
circles.emplace_back(2, 42, 10); // Compliant
}
Exceptions
The rule does not raise an issue when emplace_back
is not exception-safe. For example, when emplacing a raw new expression in a
container of smart pointers, the memory will be leaked if emplace_back
throws an exception.