vector::push_back function


The well known push_back function of vector,it’s purpose is to add element at the end of the vector.

T : data type of the vector.

1 void push_back(T&& x) ; (C++11)
2 void push_back(const T& x);

A detail discussion of these two functions is given below.


void push_back(T&& x) ; (C++11)


Parameters:
x – rvalue to be added at the end of the vector.

Return type
void

This function is called when the data to be added is a rvalue,for instance a literal.Since it accept a rvalue it moves the data instead of copying the data.

Code example

vector<int> vec ;

vec.push_back( 23 ) ; ///calls this version

cout<< vec[0] ;

Output

23

Size and capacity

This function increase the capacity of the vector if the storage is not reserve previously.However,if the storage is reserve using the reserve() function ,calling this function only increases it’s size not it’s capacity.The capacity will increase when you add data more than the reserved size.

Link:vector::reserve function

vector<string> vecSt={“Angry” } ,
vecSt1 ;

cout<< “vecSt capacity before calling push_back=” << vecSt.capacity() ;

vecSt.push_back( “Sad” ) ;///calls this version

cout<< “vecSt capacity after calling push_back=” << vecSt.capacity( ) ;

vecSt1.reserve( 3 ) ; ///Size reserve for three elements

vecSt1.push_back( “Jealousy” ) ;
vecSt1.push_back( “Hatred” );
vecSt1.push_back( “Crime” );

cout<< “vecSt1 capacity after calling push_back=” << vecSt1.capacity( ) ;

vecSt1.push_back(“Law”) ;

cout<< “vecSt1 capacity after adding 4th data=” << vecSt1.capacity( ) ;

Output

vecSt capacity before calling push_back= 1
vecSt capacity after calling push_back= 3
vecSt1 capacity after calling push_back=3
vecSt1 capacity after adding 4th data=6 (capacity increased)

Moving lvalue

If you pass a lvalue then the second push_back version is called.However if you want to call this function to move a lvalue to the vector,then use the function std::move( ).

vector<int> vec;
int val=90 ;

vec.push_back( val ) ; ///calls the second version

vec.push_back( std::move( val )); ///calls this version

Using push_back with user-defined type

When the type is a user-defined type:class or structure,and if the constructor accepts only one argument then you can simply use push_back to add an object of the type or you can pass a data of the argument type of the constructor.

class Data
{
int i;

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

~Data ( ) { }
};

vector<Data> vec;

vec.push_back( Data(78) ) ;///adding an object of Data

vec.push_back( 89 ); ///work fine,Data constructor accept integer

Passing raw data is acceptable because the push_back function will create a temporary object of the type,this temporary object is again copied into the vector.

If the vector type constructor accept more than one argument you can use push_back to add only an object of the type,you cannot pass raw data arguments.The push_back cannot accept two arguments,so it cannot create an object from the arguments passed.

class Type
{
int i;
string s ;

public:
Type/span>(int ii ,string ss):i(ii),s(ss) { }

~Type( ) { }
};

vector<Type> vec;

vec.push_back( Type(78 , “Hello”) ) ;///adding an object of Type

vec.push_back( 89 ,”World” ); ///Error!






void push_back( const T& x ) ;


Parameters:
x – value to be added at the end of the vector.

Return type
void

This version of push_back simply adds the value at the end of the container.In calling this function also the capacity remains the same if the the vector has reserve some storage else the capacity will increased along with it’s size.

Code example

vector<int> vec={23} , vec1 ;
int val=90 , &ref=val ;

vec1.reserve( 2 );

cout<< “vec capacity before push_back call=” << vec.capacity( ) << endl ;

vec.push_back( ref ) ;

cout<< “vec capacity after push_back call=” << vec.capacity( ) << endl ;

cout<< “vec capacity before push_back call=” << vec1.capacity( ) << endl ;

vec1.push_back( ref ) ;

cout<< “vec capacity after push_back call=” << vec1.capacity( ) << endl;

Output

vec capacity before push_back call=1
vec capacity after push_back call=3
vec1 capacity before push_back call=2
vec1 capacity after push_back call=2


 


Stop wasting time,earn money($$$) from your website-Join Now!

push_back invalidates iterators,pointers and reference, referring to the vector if the size exceeds the current capacity.

Suppose a storage is not reserve for the vector and an iterator points to the vector.Calling this function will increment the size and it’s capacity,this will invalidate the iterator.Consider the code example given below.

Code example

vector<char> vecC={‘B’ , ‘M’ } ;

vector<char>::iterator vecCIt=vecC.begin( ) ;

cout<< vecCIt[0] << ” ” << vecCIt[1] << endl;

vec.push_back( ‘L’ ) ;

cout<< vecCIt[0] ;//undefined ,vecCIt is invalidated

Output

B M
undefined value

However if you have reserve some storage then the iterator is valid as long as the element added is less than or equal to the reserve size.Once you add a data more than the current reserve size the iterator becomes invalid.

Code example

vector<int> vec ;

vec.reserve( 2 );

vector<int>::iterator vecIt=vec.begin( ) ;

vec.push_back(90);

cout<< vecIt[0] << vec[1] << endl; ///work fine

ve.push_back(45) ;

cout<< vecIt[0] << ” ” vecIt[1] << endl; ///work fine

vec.push_back( 505 ) ; //adds the 3rd data

cout<< vecIt[0] endl ; //undefined
<< vecIt[1] ;//undefined

Output

90
90 45
undefined value
undefined value

When the data added exceeds the reserve size a new allocation is made.With this reallocation the storage will have new addresses, but the iterator is still pointing to the previous storage which has now become invalid.Hence the iterator is invalid.