Vector usually deals with primitive data types like int, string, double. However, there would be complexities and overhead arising when dealing with vector of class objects.
For example, what will be output of below C++ program.
#include <bits/stdc++.h>
using namespace std;
// class x
class x{
int i;
public:
x(){
cout<<"constructor"<<'\n';
i = 1;
}
x(const x &p2){
cout<<"copy constructor"<<'\n';
}
~x(){
cout<<"destructor"<<'\n';
}
};
// driver program
int main()
{
// vector
vector<x> v;
v.reserve(7);
x obj;
for(unsigned i=0;i<6;i++){
v.push_back(obj);
}
return 0;
}
How many constructors will be called here?
How many constructors will be called?
How many destructors will be called?
The output of above program is :
constructor copy constructor copy constructor copy constructor copy constructor copy constructor copy constructor destructor destructor destructor destructor destructor destructor destructor
There will be one constructor when we define object obj of class x. 7 copy constructors when we push_back object into the vector and 8 destructors, one for obj and 7 for class x objects pushed into the vector.
Now let us tweak the program a bit and see what is the output:
#include <bits/stdc++.h>
using namespace std;
// class x
class x{
int i;
public:
x(){
cout<<"constructor"<<'\n';
i = 1;
}
x(const x &p2){
cout<<"copy constructor"<<'\n';
}
~x(){
cout<<"destructor"<<'\n';
}
};
// driver program
int main()
{
// vector
vector<x> v;
v.reserve(7);
x obj;
for(unsigned i=0;i<8;i++){
v.push_back(obj);
}
return 0;
}
The output of above program is:
constructor copy constructor copy constructor copy constructor copy constructor copy constructor copy constructor copy constructor copy constructor copy constructor copy constructor copy constructor copy constructor copy constructor copy constructor copy constructor destructor destructor destructor destructor destructor destructor destructor destructor destructor destructor destructor destructor destructor destructor destructor destructor
Since we reserved space for only 8 objects, when the 8th object is copied, OS needed to allocate bigger storage somewhere else.
So, it has to copy the already existing objects from older storage to new storage, thus calling copy constructors. Allocate storage for new object to be pushed back into vector. Now, here comes releasing the old storage thus calling 16 destructors. Finally it calls 16 destructors when the program terminates.
Note :
- When the vector runs out of its reserved space by user, it does not throw error. It allocates bigger storage somewhere.
- Copy existing elements from old storage to new storage.
- Appends new element to the vector.
- Releases memory allocated to old storage.
Thus in a class when you are keeping count of how many objects of a class is created using some static variable in its copy constructor, do not get confused by this behavior when you are using vector of that class objects.
Please write comments if you find anything incorrect. A gentle request to share this topic on your social media profile.
