vector构建和销毁需要注意的两个问题
2010-03-31 17:54
549 查看
【关于vector的构建】向vector容器添加对象,vector会在指定的位置保存一个该对象的副本,因此拷贝构造函数会被调用。下面是对push_back()函数的官方解释:
1. 创建一个临时对象,会调用默认构造函数;
2. 然后,使用该临时对象初始化vect中的10元素,从而出现了10次拷贝构造函数调用;
3. 初始化完毕后,释放该临时对象,调用析构函数;
4. 向vect尾部添加元素b,vect需要重新分配空间大小容纳新的元素,开辟11个Test对象空间并进行初始化,产生11次拷贝构造函数的调用;
5. main()函数结束,vect生命周期结束,释放所有元素,产生11次析构函数调用。
通过以上例子,我们发现vector直接保存对象的额外开销非常之大,主要是拷贝构造函数的调用,而一个较为好的解决方式是保存对象的指针或share_ptr。
【关于vector的销毁】
// Adds a new element at the end of the vector, after its current last element. // The content of this new element is initialized to a copy of x. void push_back(const T& x);下面是vc++6.0下面的一个示例代码:
#include <iostream>; #include <vector>; using namespace std; class Test { public: Test() { n = 0; cout << "default constructor is called!" << endl; } explicit Test(int m) { n = m; } Test(const Test& other) { count++; // 对拷贝构造函数调用进行计数 n = other.n; cout << "copy constructor is called" << count << "th" << endl; } ~Test() { cout << "destructor is called!" << endl; } public: static int count; int n; }; int Test::count = 0; int main() { Test b(10); vector<test> vect(10); // 初始化vect空间大小为10 Test::count = 0; // 重置i的值为零,对拷贝构造函数调用次数重新计数 vect.push_back(b); return 0; } // 这段代码的输出(VC++6.0): default constructor is called! copy constructor is called 1th copy constructor is called 2th copy constructor is called 3th copy constructor is called 4th copy constructor is called 5th copy constructor is called 6th copy constructor is called 7th copy constructor is called 8th copy constructor is called 9th copy constructor is called 10th destructor is called! copy constructor is called 1th copy constructor is called 2th copy constructor is called 3th copy constructor is called 4th copy constructor is called 5th copy constructor is called 6th copy constructor is called 7th copy constructor is called 8th copy constructor is called 9th copy constructor is called 10th copy constructor is called 11th destructor is called! destructor is called! destructor is called! destructor is called! destructor is called! destructor is called! destructor is called! destructor is called! destructor is called! destructor is called!对于以上输出内容的解释:
1. 创建一个临时对象,会调用默认构造函数;
2. 然后,使用该临时对象初始化vect中的10元素,从而出现了10次拷贝构造函数调用;
3. 初始化完毕后,释放该临时对象,调用析构函数;
4. 向vect尾部添加元素b,vect需要重新分配空间大小容纳新的元素,开辟11个Test对象空间并进行初始化,产生11次拷贝构造函数的调用;
5. main()函数结束,vect生命周期结束,释放所有元素,产生11次析构函数调用。
通过以上例子,我们发现vector直接保存对象的额外开销非常之大,主要是拷贝构造函数的调用,而一个较为好的解决方式是保存对象的指针或share_ptr。
【关于vector的销毁】
#include <string.h> #include <vector> using namespace std; class Test { public: Test() : m_pch(0) {} Test(const char* p) { if ( p ) { m_pch = new char[strlen(p) + 1]; strcpy(m_pch, p); } } ~Test() { delete[] m_pch; m_pch = 0; } private: char* m_pch; }; int main() { vector<test> vect; Test t("Hello World!"); vect.push_back(t); return 0; } // 以上程序出现致命错误,由于Test默认拷贝构造函数执行的是浅拷贝,m_pch指向的内存被t和vect两次释放,程序出现崩溃。
相关文章推荐
- 协程设计需要注意的两个小问题及解决
- 网络数据传输需要注意的两个问题
- 两个页面之间传值需要注意的问题
- [置顶] java Vector 在多线程使用中需要注意的问题
- vector使用需要注意的一些问题
- 网络数据传输需要注意的两个问题
- STL::vector两个值得注意的问题
- nginx往后端转发时需要注意的两个问题
- IBM WebSphere Portal6.1配置数据库和LDAP时需要注意的两个问题
- 在代码中设置ListView的divider,需要注意的两个问题
- 编写守护脚本需要注意的的两个问题
- 重载赋值运算符中需要注意的两个问题
- Tcp流套接字两个需要注意的问题:粘包和包分段
- 第九章:重载赋值运算符中需要注意的两个问题
- 在 Hyper-V 上安装 CentOS 系统需要注意的两个问题
- sql server 2005笔记——将数据库从2000还原到2005需要注意的两个问题
- c++两个类相互调用需要注意的问题
- 如果一个页面中用了两个以上displaytag,需要注意的分页问题
- iOS 后台定位需要注意的两个问题
- MySQL处理空值时你需要注意的两个问题