在做C++ Primer 5th的联系13.13时有一个很有意思的现象:当一个声明一个保存自定义类类型的vector时,如果在进行push_back操作之前这个vector的capacity和其size一致的话,则程序会向操作系统申请更多的内存以保存更多的元素。此时,整个vector会对其已经构建的元素重新全部构建一次(即调用拷贝构造函数),然后再在末尾元素之后构建新的元素。最后调用析构函数销毁扩容之前构建的元素。
下面直接看程序:
//X结构体的定义 struct X { //默认构造函数 X() { cout << "X()" << endl; } //拷贝构造函数 X(const X&) { cout << "X(const X&)" << endl; } //拷贝赋值运算符 X& operator=(const X&) { cout << "operator=(const X&)" << endl; } //析构函数 ~X() { cout << "~X()" << endl; } }; int main(int argc, char** argv) { vector<X> vec_X; //vec_X.reserve(3); //如果不进行预留空间 //则vector进行push_back的时候 //会重复构建之前已经push_back的元素 for(unsigned i = 0; i < 5; ++i) { X temp_x; //调用默认构造函数 vec_X.push_back(temp_x); //void push_back ( const T& x ); //传参时,调用拷贝构造函数,构造一个对象 //添加到vector的末尾 cout << vec_X.capacity() << " "; //离开for循环,temp_x被销毁,调用析构函数 } cout << endl; return 0; }
运行的结果为:
从运行结果可以看出:
添加第一个元素时,只调用了一次X的拷贝构造函数;
添加第二个元素前,此时的capacity为1,所以要为容器扩容,扩容后为2,添加第二个元素时,却调用了两次拷贝构造函数,最后调用析构函数销毁扩容前的第一个元素;
添加第三个元素时,也同理,重新构造了前两个已经构造的元素,再构造第三个元素添加至末尾;
添加第四个元素前,capacity为4,足够再添加多一个元素,则只调用了一次拷贝构造函数;
添加第五个元素前,capacity与size一致,需要扩容,则容器重新构造了前四个元素,然后再构造第五个元素添加至末尾,最后销毁扩容前构造的四个元素;
程序结束退出,调用5次析构函数销毁vector内的5个元素。
另外参考了一篇文章:http://blog.csdn.net/mfcing/article/details/8746256
这篇文章详细说明了——关于vector,简单地讲就是一个动态数组,里面有一个指针指向一片连续的内存空间,当空间不够装下数据时会自动申请另一片更大的空间,然后把原有数据拷贝过去,接着释放原来的那片空间;当释放或者说是删除里面的数据时,其存储空间并不会释放,仅仅只是清空了里面的数据。