C++ difference between emplace_back and push_back function


Although C++ emplace_back and push_back functions sole purpose is to append data at the end of the vector,their exists some differences between them.And one of the petty differences which might be worth mentioning is push_back function has been part of the Standard C++ from the time of it’s creation ,the emplace_back function however is a new addition to the language.It is added recently under C++11 features.So some might not be even familiar with the emplace_back function.

If you are new to C++ and not familiar with either of the functions ,please read about them first;visit the links provided below.This post only explain the differences that exist between emplace_back and push_back functions.I won’t be explaining here on how to use them.

Link: vector::push_back function
Link: vector::emplace_back function

Difference 1: push_back accepts only object of the type if the constructor accept more than one arguments,whereas emplace_back accept arguments of the constructor of the type.

When the vector type is a user-defined type:class or structure,and the constructor of the type accepts more than one argument,in such case calling the push_back function requires that we pass an object of the type.But in calling the emplace_back we can simply pass the arguments of the type of the constructor instead of passing the object itself.

Note this difference arises only when the constructor accept more than one argument.In constructor accepting only one argument when calling the push_back we can pass the argument of the type of the constructor instead of passing the object.This acceptance of raw data -instead of object- in push_back for one argument constructor is due to the C++11 version of push_back function.The C++11 version allows construction of object from the argument passed,which is then pushed into the vector container.

If the constructor accepts two or more arguments you must passed the object of the type explicitly.

Link:vector::push_back C++11 version

Code example:For class with constructor accepting one argument.

class Test
{
int i;

public:
Test(int ii):i(ii) { } //constructor

int get const() { return i; }

~Test( ) { }
};

int main( )
{
vector<int> vec={ 21 , 45 };

vec.push_back( Test(34) ) ;///Appending Test object by passing Test object

vec.push_back( 901 ) ; //Appending Test object but int data is passed,work fine

vec.emplace_back( Test(7889) ); ///work fine

vec.emplace_back( 4156 ) ; ///work fine

for( auto elem:vec )
{
cout<< elem.get() << ” ” ;
}

cin.get( );
return 0;
}

Output

21 45 34 901 7889 4156

Here is another code example when the constructor accept two arguments.

Code example:Class with constructor accepting two arguments

class New
{
int i;
string st;

public:
New(int ii, string s):i(ii) , st(s) { }

int getInt const() { return i; }

string getString const () { return st; }

~New( ) { }
};

int main( )
{
vector<int> vec={ {21,”String”} , New{45 , “tinger”} } ;

vec.push_back( New(34 , “Happy” ) ) ; //Appending Test object

vec.push_back( 901 , “Doer” ) ; //Error!

vec.emplace_back( New(78 , “Gomu gomu” ) ); ///work fine

vec.emplace_back( 41 , “Shanks” ) ; ///work fine

for( auto elem:vec )
{
cout<< elem.getInt( ) << ” ” << elem.getString( ) << endl ;
}

cin.get( ) ;
return 0 ;
}

Output

21 String
45 Tinger
34 Happy
78 Gomu gomu
41 Shanks

The first push_back call suceeds because we have passed a New object,but the second push_back call fails because the push_back simply cannot accept two arguments.The emplace_back on the other hand happily accept the two arguments passed to it.

In recieving the arguments the emplace_back create an object of New by calling the constructor and append the object to the vector and so the call succeeds.

The bottom line is if you use push_back and the type is ‘class’ or ‘struct’ with constructor accepting one argument then you can pass the data of the class instead of passing the object explicitly.But,if the class constructor accept more than one argument you are only allowed to pass the object of the class.In emplace_back function however whether the class accept one or more arguments you can pass the object or the datas of the type accepted by the constructor of the class,either way it works fine.My advise is prefer emplace_back over push_back function usage.



Difference 2:Efficiency

In C++ when discussing two features having similar usage, there always remain a question,which is more efficient? When we say ‘efficient’ we can mean ‘a faster working code :producing lesser overhead‘ or ‘easier maintainable code: more versatile and easier to maintain‘.Here when I say ‘efficient’ I will be referring to ‘faster working code’.

In this section let us compare the efficiency of push_back and emplace_back function when various types are used.First we will discuss when the type is built-in type and then we will their efficiency when the type is user-defined type.

built-in type

If the type is a built-in type there is no difference in efficiency between push_back and emplace_back function.

User-defined type

For class or structure with constructor accepting one argument.Passing a data of the type accepted by the constructor is more efficient than passing the object of the type-for both push_back and emplace_back.If a raw data is passed the object is constructed directly in the storage managed by the vector.Such process eliminate any overhead that might otherwise occur in some other situation.

Suppose if we try to append the object-instead of data accepted by the constructor of the class- directly to the vector,then here a temporary object is created first.After the temporary object creation it is then copied into the vector.Here copying of temporary object into the vector storage produce an overhead which decreases the efficiency of the code.Note in the first process-passing raw data instead of object of the class- there is no copying of data from the temporary storage to the vector storage ,hence the overhead produced by this process is eliminated.

Code example

class Dat
{
int i;

public:
Dat(int ii):i(ii) { }

~Dat( ) { }
};

vector<Dat> vec ;

vec.push_back( Dat(89) ); ///efficiency lesser

vec.push_back( 67 ); //efficiency is more ,C++11 version is called

vec.emplace_back( 890 ); ///efficiency same as the above push_back

In the first push_back call a temporary object is created first by calling the constructor.But in the second push_back and emplace_back function call the object is created directly into the vector.And hence there is no need for copying the object into the vector.

If the constructor accept more than one argument and if push_back is used our only option is to pass an object of the type explicitly.This in turn will lead to the creation of temporary object which is then copied into the vector.This means using push_back to add object of class with more than one argument will always produce an overhead .But note emplace_back does not have such limitation-whether the class has more than one argument or not it can always accept raw data.So it is better that you use emplace_back function which increase the efficiency of the code by constructing the object directly into the memory managed by the vector.

class Bat
{
int i ;
string ss ;
char c ;

public:
Dat(int ii , string s, char cc):i(ii) , ss(s) , c(cc) { }

~Dat( ) { }
};

vector<Dat> vec ;

vec.reserve( 3 );

vec.push_back( Dat(89, “New” , ‘G’ ) ); //efficiency lesser

vec.push_back( 678 , “Newer” , ‘O’ ); //error,push_back can’t accept three arguments

vec.emplace_back( 890 , “Newest” , ‘D’ ); //work fine,efficiency is also more

The pictorial representation below might help you understand better.

difference between emplace_back and push_back

The copying process is omitted in emplace_back function call.


Related links

->C++11 vector emplace

->C++ vector insert

->C++ reserve vector

->C++ capacity vector

->C++ size vector