Table of Contents#
- What is
emplace_back? - How does
emplace_backdiffer frompush_back? - Syntax and Usage
- Common Practices
- Best Practices
- Example Usage
- Conclusion
- References
What is emplace_back?#
emplace_back is a member function of the std::vector class in the C++ STL. Its primary purpose is to construct an object in - place at the end of the vector. Instead of creating an object first and then moving or copying it into the vector (which is what push_back often does), emplace_back directly constructs the object within the vector's memory space. This can lead to significant performance improvements, especially when dealing with complex or expensive - to - copy objects such as objects with non - trivial constructors or large data members.
How does emplace_back differ from push_back?#
push_back#
- Copy and Move Semantics: When you use
push_backwith an lvalue (a named variable), it creates a copy of the object and adds it to the vector. When using an rvalue (a temporary object), it attempts to move the object into the vector. In some cases, this can involve redundant copy or move operations. - Object Pre - construction: The object must be fully constructed before being passed to
push_back, which can be inefficient for large or complex objects.
emplace_back#
- In - place Construction:
emplace_backtakes the arguments necessary to construct the object and constructs it directly in the vector's memory. This avoids unnecessary copy or move operations, potentially saving a significant amount of time and memory. - Flexibility: It can accept multiple arguments, which are then forwarded to the object's constructor. This allows for more flexible and efficient construction of objects within the vector.
Syntax and Usage#
The syntax of emplace_back is as follows:
template< class... Args >
void emplace_back( Args&&... args );Here, Args is a parameter pack that can hold any number of arguments. These arguments are forwarded to the constructor of the vector's element type.
To use emplace_back, you simply call it on a std::vector object and pass the necessary constructor arguments. For example:
#include <vector>
#include <iostream>
class MyClass {
public:
MyClass(int a, double b) : num(a), val(b) {
std::cout << "MyClass constructed with " << a << " and " << b << std::endl;
}
private:
int num;
double val;
};
int main() {
std::vector<MyClass> myVector;
myVector.emplace_back(10, 3.14);
return 0;
}In this example, emplace_back constructs a MyClass object directly in the myVector using the provided arguments 10 and 3.14.
Common Practices#
- Use with Complex Objects: Whenever you are working with objects that have expensive copy or move constructors, such as classes with large dynamic arrays or complex member objects, use
emplace_backinstead ofpush_back. - Pass Constructor Arguments: Instead of creating an object first and then passing it to
emplace_back, pass the constructor arguments directly. This allows for in - place construction and avoids unnecessary object creation.
Best Practices#
- Check Memory Requirements: Before calling
emplace_back, make sure your vector has enough capacity to accommodate the new element. You can use thereservefunction to pre - allocate memory and avoid unnecessary reallocations.
std::vector<MyClass> myVector;
myVector.reserve(10); // Reserve space for 10 elements
myVector.emplace_back(10, 3.14);- Error Handling: Keep in mind that if the construction of the object fails (e.g., due to a bad allocation or an exception thrown in the constructor), the vector remains unchanged. However, you should still handle exceptions appropriately in your code.
Example Usage#
Simple Example#
#include <iostream>
#include <vector>
#include <string>
struct Person {
std::string name;
int age;
Person(const std::string& n, int a) : name(n), age(a) {
std::cout << "Person " << name << " constructed." << std::endl;
}
};
int main() {
std::vector<Person> people;
people.emplace_back("Alice", 25);
people.emplace_back("Bob", 30);
for (const auto& person : people) {
std::cout << person.name << " is " << person.age << " years old." << std::endl;
}
return 0;
}In this example, we create a std::vector of Person objects. Using emplace_back, we directly construct Person objects within the vector by passing the constructor arguments.
Using with Custom Classes#
#include <iostream>
#include <vector>
#include <memory>
class Resource {
public:
Resource(int id) : resourceId(id) {
std::cout << "Resource " << resourceId << " created." << std::endl;
}
~Resource() {
std::cout << "Resource " << resourceId << " destroyed." << std::endl;
}
private:
int resourceId;
};
class Container {
public:
Container(std::unique_ptr<Resource> res) : resource(std::move(res)) {}
private:
std::unique_ptr<Resource> resource;
};
int main() {
std::vector<Container> containers;
containers.emplace_back(std::make_unique<Resource>(1));
return 0;
}This example demonstrates using emplace_back with a class that takes a std::unique_ptr as a constructor argument. The emplace_back function constructs the Container object directly in the vector, forwarding the std::unique_ptr to the constructor.
Conclusion#
The emplace_back function in the C++ STL provides a powerful and efficient way to add elements to a std::vector. By constructing objects in - place, it avoids unnecessary copy and move operations, leading to better performance, especially for complex objects. By following the common and best practices outlined in this blog, you can make the most of emplace_back in your C++ code.
References#
- C++ Standard Library documentation: https://en.cppreference.com/w/cpp/container/vector/emplace_back
- "The C++ Programming Language" by Bjarne Stroustrup
- "Effective Modern C++" by Scott Meyers