Do you think IIT Guwahati certified course can help you in your career?
No
Introduction
In C++, various containers can store other objects or elements. For example, array, vector, deque, list, etc. Vector is a very popular container to store elements with the same data types. This article will talk about how to insert elements in vectors using push_back() and emplace_back() and the difference between these two functions.
What are Vectors?
Vectors are dynamic arrays that can store elements of the same data types. The size of the vectors can change during runtime whenever we add or delete an element. The elements in a vector are stored in contiguous memory locations and can be traversed and accessed easily.
push_back
Push_back: Push_back adds a new element at the end. It first creates a temporary object by calling a constructor.
Implementation in C++
Here is an example implementation of the push_back() function in C++:
void push_back(const T& value) {
if (size_ == capacity_) {
reserve(2 * capacity_); // double the capacity of the vector
}
data_[size_] = value; // insert the new element at the end of the vector
size_++; // increment the size of the vector
}
You can also try this code with Online C++ Compiler
The function takes a single argument of type T, which is a reference to the value to be added to the end of the vector. If the current size of the vector is equal to its capacity (i.e., there is no more space to add new elements), the reserve() function is called to allocate additional memory to the vector. In this case, the capacity of the vector is doubled to make room for more elements. The new element is inserted at the end of the vector by assigning its value to the next available index in the vector's internal array, data.
Emplace_back
Emplace_back: It also Inserts a new element at the end. It does not create a temporary object. The object is directly created in the vector. Due to this, the efficiency is increased.
Implementation in C++
Here is an example implementation of the emplace_back() function in C++:
template <typename... Args>
void emplace_back(Args&&... args) {
if (size_ == capacity_) {
reserve(2 * capacity_); // double the capacity of the vector
}
new (&data_[size_]) T(std::forward<Args>(args)...); // construct the new element in place
size_++; // increment the size of the vector
}
You can also try this code with Online C++ Compiler
The function takes a variable number of arguments of any type, Args&&... args, using template parameter pack.
If the current size of the vector is equal to its capacity (i.e., there is no more space to add new elements), the reserve() function is called to allocate additional memory to the vector. In this case, the capacity of the vector is doubled to make room for more elements.
The new element is constructed in place at the end of the vector using placement new. This means that the memory for the new element is allocated from the vector's internal array, data_, and the constructor of the element is called directly in that memory location.
The std::forward function is used to forward the arguments to the constructor of the new element, preserving their original value category (i.e., lvalue or rvalue).
Finally, the size of the vector is incremented to reflect the addition of the new element.
The difference in the efficiency of push_back and emplace_back depends on the type of our vector. If the vector is a built-in type, there is no difference between the efficiency of push_back and emplace_back. If the vector type is class or struct, emplace_back is more efficient than push_back.
What happens when we call push_back?
Push_back inserts the elements from the end. The size of the vector is increased by one after inserting the element.
The steps involved in push_back are
A temporary object is created by calling a constructor.
It then resizes the vector, and then the temporary object is passed to the new memory location.
Then, a destructor will be called to destroy the temporary object after copying.
Push_back example
// CPP program to illustrate push_back
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int count = 0;
vector<char> vec;
vec.push_back('C');
vec.push_back('O');
vec.push_back('D');
vec.push_back('I');
vec.push_back('N');
vec.push_back('G');
vec.push_back(' ');
vec.push_back('N');
vec.push_back('I');
vec.push_back('N');
vec.push_back('J');
vec.push_back('A');
vec.push_back('S');
cout<<"C++ program to illustrate push_back"<<endl<<"The vector is: ";
for(int i=0;i<vec.size();i++)
cout << vec[i];
return 0;
}
Output:
What happens when we call emplace_back
Emplace_back was added in C++11. It adds a new element at the end of the vector. This new element is constructed using args as the arguments for its constructor. No temporary element is created in this case.
Emplace_back example
#include <iostream>
#include <string>
#include <vector>
using namespace std;
struct CN {
std::string s;
CN(std::string str) : s(std::move(str)) { std::cout << " constructed\n"; }
CN(const CN& o) : s(o.s) { std::cout << " copy constructed\n"; }
CN(CN&& o) : s(std::move(o.s)) { std::cout << " move constructed\n"; }
CN& operator=(const CN& other) {
s = other.s;
std::cout << " copy assigned\n";
return *this;
}
CN& operator=(CN&& other) {
s = std::move(other.s);
std::cout << " move assigned\n";
return *this;
}
};
int main()
{
std::vector<CN> container;
// reserve enough place so vector does not have to resize
container.reserve(5);
std::cout << "construct 2 times CN:\n";
CN two { "two" };
CN three { "three" };
std::cout << "emplace:\n";
container.emplace(container.end(), "one");
std::cout << "emplace with CN&:\n";
container.emplace(container.end(), two);
std::cout << "emplace with CN&&:\n";
container.emplace(container.end(), std::move(three));
std::cout << "content:\n";
for (const auto& obj : container)
std::cout << ' ' << obj.s;
std::cout << '\n';
}
Output:
Difference between Vector push_back() and emplace_back()
Parameters
push_back()
emplace_back()
Usage
Add a copy of the object at the end of the vector
Construct the object in-place at the end of the vector
Arguments
Takes an object of the same type as the vector
Takes constructor arguments for the object to be constructed
Performance
Copies the object, potentially leading to extra overhead due to copying
Constructs the object directly in the vector, potentially leading to improved performance
If performance is a concern, emplace_back() is generally better than push_back() since it constructs the object in-place, potentially avoiding a copy operation. However, push_back() is simpler to use and can be more appropriate in certain situations.
What is the difference between list Emplace_back and Push_back?
emplace_back() constructs the object in-place at the end of the list, potentially improving performance by avoiding a copy operation, while push_back() adds a copy of the object to the end of the list. Additionally, emplace_back() requires constructor arguments for the object to be constructed.
What is the difference between emplace front and push front?
emplace_front() constructs the object in-place at the beginning of the list, potentially improving performance by avoiding a copy operation, while push_front() adds a copy of the object to the beginning of the list.
Is emplace better than insert?
emplace() and insert() have different use cases. emplace() constructs an object in-place at a specified position, potentially avoiding a copy operation, while insert() adds a copy of the object at the specified position. Both have their own advantages and may be better depending on the use case.
Conclusion
This blog talked about two methods to insert elements at the end of the vector: emplace_back and push_back. We saw the difference between them and also implemented them in our code.
There are more data structures that one must be familiar with. To get a complete understanding of various data structures, check out our data structures and algorithms course on coding ninjas.