Comparing push_back() and emplace_back() in C++
Push_back() vs. emplace_back(): What's the difference in C++?
Here's an improved version of your blog post:
Understanding emplace_back
in C++: A Simple Guide
When working with C++ vectors, adding new elements is a common task. Two popular methods for doing this are push_back
and emplace_back
. While they might seem similar at first glance, emplace_back
has some unique advantages that make it a powerful tool in certain situations.
What Makes emplace_back
Special?
The emplace_back
function is designed to add a new element directly to the end of a vector. What sets it apart is that it constructs the element in place, right in the vector's memory. This means there's no need to create a temporary object first, which can then be copied or moved into the vector. This can save both time and memory, especially when working with complex objects.
A Real-World Example: String Hashing
Let's look at a practical example inspired by a common problem in competitive programming: finding duplicate strings in an array using string hashing.
int compute_hasing(string const& s) {
int n = s.size();
int hash = 0;
int p = 31;
int power = 1;
int mod = 1e9 + 9;
for (int i = 0; i < n; i++) {
hash = (hash + (s[i] - 'a' + 1) * power) % mod;
power = (power * p) % mod;
}
return hash;
}
void findHashForEachString(vector<string> const& v) {
vector<pair<int, int>> p;
int n = v.size();
for (int i = 0; i < n; i++) {
p.push_back(make_pair(compute_hasing(v[i]), i));
}
sort(p.begin(), p.end());
vector<vector<string>> groups;
for (int i = 0; i < n; i++) {
if (i == 0 || p[i].first != p[i - 1].first) {
groups.emplace_back();
}
groups.back().push_back(v[p[i].second]);
}
for (const auto& group : groups) {
for (const auto& str : group) {
cout << str << " ";
}
cout << endl;
}
}
How emplace_back
Is Used in This Code
In this function, emplace_back()
is used to create a new empty vector whenever a new group of strings with the same hash is found. Here's how it works:
Grouping Strings by Hash: As we process each string, we compare its hash with the previous one. If the hash is different, we know we're dealing with a new group of strings.
Creating a New Group:
emplace_back()
is called to add a new empty vector to thegroups
vector. This new vector will hold all the strings in the current group.Adding Strings to the Group: The current string is then added to this newly created vector.
This approach ensures that every time we encounter a new group of identical strings (based on their hashes), a new vector is created in groups
to hold them.
emplace_back
vs. push_back
: What's the Difference?
To really understand emplace_back
, let's compare it with push_back
using a simple example:
struct Person {
string name;
int age;
Person(string name, int age) : name(name), age(age) {
cout << "Constructed Person: " << name << endl;
}
};
int main() {
vector<Person> people;
Person john("John", 25);
people.push_back(john); // Creates a copy of 'john' and stores it in 'people'
people.emplace_back("Doe", 30); // Constructs 'Doe' directly in place
return 0;
}
With push_back
:
You first create a
Person
object namedjohn
.When you call
push_back(john)
, a copy ofjohn
is made and added to the vectorpeople
.
With emplace_back
:
You pass the arguments
"Doe"
and30
directly toemplace_back()
.It constructs the
Person
object in place within the vector, without the need for a temporary object.
Key Points
push_back
: Requires an existing object or temporary object to be moved or copied into the vector.emplace_back
: Constructs the object directly in place using the provided arguments, which can save resources and avoid unnecessary copies.