Chinaunix首页 | 论坛 | 博客
  • 博客访问: 322566
  • 博文数量: 4
  • 博客积分: 2500
  • 博客等级: 少校
  • 技术积分: 785
  • 用 户 组: 普通用户
  • 注册时间: 2006-05-29 22:29
文章分类
文章存档

2011年(1)

2009年(1)

2008年(2)

我的朋友

分类: C/C++

2009-04-10 17:13:27

在使用std的容器的时候,不少人喜欢用vector, 因为比起list,更省空间,而且可以根据index直接读取某个值,而不用一个个枚举来取.

但是,std::vector确实有一些值得注意的陷阱, 这里先说其中一个, 请看以下代码.

std::vector< int >  values;

values.push_back(1);

values.push_back(2);

values.push_back(3);

values.erase(values.begin() + 1);

乍看之下,这几行简单的代码没什么 问题. 实际执行起来, 还是没什么问题 , 但却有一个陷阱. 由于例子里面用的是int的vector,所以这样做没有任何问题, 但,假如不是一个int, 而是一个类,一个结构体,类或结构体里面还有指针, 那就很可能出问题了. why?

因为vector不象list,vector始终要保持一个完整的内存结构(因为就是一个数组),这样才可以让values[1]这样的方式正确运行. 但是,如果要在vector中间删掉一个成员的话,vector是这样做的, 先把该成员后面的一个成员,一直到最后一个成员往前一位置拷贝,这样需要删除的成员已经被后面的覆盖了, 然后再删除最后一个成员,这样,vector又能保持一段完整的内存结构了.  注意,因为最后一个成员会被删除,而如果这个成员里面有一个成员变量是指针, 那析构函数很有可能会把这个指针指向的地方释放掉!  这样,即使最后一个成员被复制了一份 到倒数第2的位置,也因为在他本身被删除的时候,把倒数第2个(也就是它的复制) 的指针成员所指向的地方给释放了! 如图:

                      

解决的办法也很简单, 最少有2种. 1,  增加作为vector类型的类的拷贝构造函数, 因为vector在erase的时候会发生一次拷贝,让拷贝构造函数不单单是复制指针,还把指针所指向的内容给拷贝一份,这样就不会导致被最后一个成员释放的时候一起释放掉了. 2, 如果有引用记数的话,如智能指针, 就不会被释放掉了。不过如果一般编码里面不需要用到引用记数的话,还是方法1比较简便.

阅读(3213) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~