如果容器中包含了通过new操作创建的指针,切记在容器对象析构前将指针delete掉

在STL中容器是智能的,可以在容器销毁时自动调用容器里对象的析构函数来销毁容器存储的对象。

STL的容器虽然比较智能,但是没有智能到可以自动销毁new出来的指针对象。

所以在使用STL中的容器时,如果保存的是mew出来的对象的指针。如果在容器销毁之前没有把new出来的对象释放,会造成内存泄露。

解决方法版本一:

  1. void doSomething()
  2. {
  3. vector<Widget*> vwp;
  4. ...
  5. for (vector<Widget*>::iterator i = vwp.begin();i != vwp.end(),++i)
  6. {
  7. delete *i;
  8. }
  9. }

这种手工释放容器里new的对象不太可靠,菲异常安全的。如果在delete的时候爆出异常,那么还是会引起内存泄露。

解决方法二:

  1. template<typename T>
  2. struct DeleteObject : public unary_function<const T*, void>
  3. {
  4. void operator()(const T* ptr) const
  5. {
  6. delete ptr;
  7. }
  8. };

这是一个函数对象。

  1. void doSomething()
  2. {
  3. ... // 同上
  4. for_each(vwp.begin(), vwp.end(), DeleteObject<Widget>);
  5. }

手动销毁new出来的对象

使用函数对象的方式,可以保证对象的安全销毁完,虽然在调用时需要指明函数对象类型,实现了适配器作用,但是这种方法需要公有继承,有个特殊情况,就是STL的string。

  1. class SpecialString: public string { ... };
  2. void doSomething()
  3. {
  4. deque<SpecialString*> dssp;
  5. ...
  6. for_each(dssp.begin(), dssp.end(),DeleteObject<string>());// 虚析构函数的基类
  7. }

string是没有虚析构函数的,所以在作为基类时,在这个对象使用完析构时,会找不到对应的析构函数,这时的行为是未知的。

解决方法三:

  1. struct DeleteObject {
  2. template<typename T> // 模板化加在这里
  3. void operator()(const T* ptr) const
  4. {
  5. delete ptr;
  6. }
  7. }
  8. void doSomething()
  9. {
  10. deque<SpecialString*> dssp;
  11. for_each(dssp.begin(), dssp.end(),DeleteObject());
  12. }

把模板化放在类里面,重载()操作符前,由编译器自动判断调用者的类型,这样就可以避免公有继承这一步操作,也就实现了通用。但是却丢弃了可适配的能力。

最优的解决方法:

  1. void doSomething()
  2. {
  3. typedef boost::shared_ ptr<Widget> SPW;
  4. vector<SPW> vwp;
  5. for (int i = 0; i < SOME_MAGIC_NUMBER; ++i)
  6. vwp.push_back(SPW(new Widget)); // 从一个Widget建立SPW,然后进行一次push_back
  7. ...
  8. // 使用vwp
  9. }

使用boost里的shared_ptr智能指针,通过其的自动计算引用计数的实现来,在使用STL容器保存new出来的对象指针时,超出作用域范围自动销毁智能指针里的对象,实现安全可靠高效的解决内存泄露方案。

总的来说,在使用STL容器存储new出来的对象的指针时,需要注意对象的析构销毁步骤。这一步是需要我们自己来管理的。

条目七《如果容器中包含了通过new操作创建的指针,切记在容器对象析构前将指针delete掉》的更多相关文章

  1. 7 -- Spring的基本用法 -- 5... Spring容器中的Bean;容器中Bean的作用域;配置依赖;

    7.5 Spring容器中的Bean 7.5.1 Bean的基本定义和Bean别名 <beans.../>元素是Spring配置文件的根元素,该元素可以指定如下属性: default-la ...

  2. 【String注解驱动开发】如何按照条件向Spring容器中注册bean?这次我懂了!!

    写在前面 当bean是单实例,并且没有设置懒加载时,Spring容器启动时,就会实例化bean,并将bean注册到IOC容器中,以后每次从IOC容器中获取bean时,直接返回IOC容器中的bean,不 ...

  3. 在 docker 容器中捕获信号

    我们可能都使用过 docker stop 命令来停止正在运行的容器,有时可能会使用 docker kill 命令强行关闭容器或者把某个信号传递给容器中的进程.这些操作的本质都是通过从主机向容器发送信号 ...

  4. 隔离 docker 容器中的用户

    笔者在前文<理解 docker 容器中的 uid 和 gid>介绍了 docker 容器中的用户与宿主机上用户的关系,得出的结论是:docker 默认没有隔离宿主机用户和容器中的用户.如果 ...

  5. 在Docker容器中搭建MXNet/Gluon开发环境

    在这篇文章中没有直接使用MXNet官方提供的docker image,而是从一个干净的nvidia/cuda镜像开始,一步一步部署mxnet需要的相关软件环境,这样做是为了更加细致的了解mxnet的运 ...

  6. docker容器中的peewee如何连接已有的容器中的数据库

    首先,两个容器必须是在同一网络下,有2个办法. 一个是在同一个docker-compose.yml文件下使用links参数,比如: version: '3' services: redis: imag ...

  7. spring在IoC容器中装配Bean详解

    1.Spring配置概述 1.1.概述 Spring容器从xml配置.java注解.spring注解中读取bean配置信息,形成bean定义注册表: 根据bean定义注册表实例化bean: 将bean ...

  8. docker容器中解决出现:^H^H^H^H

    docker容器中解决出现:^H^H^H^H 环境:docker容器是debain系统 解决: 把stty erase ^H 添加到.bash_profile中 vim /etc/profile st ...

  9. Docker拷贝宿主机与容器中的文件

    如果我们需要将宿主机文件拷贝到容器内可以使用 docker cp 命令,也可以将文件从容器内拷贝到宿主机 将宿主机文件拷贝到容器内 docker cp 要拷贝的宿主机文件或目录 容器名称:容器文件或目 ...

随机推荐

  1. Linux 学习笔记之 --- epoll 事件模型详解

    epoll 主要采用对已就绪的 fd 进行轮询操作   一.epoll 触发方式 epoll支持 ET 和 LT 两种触发方式 ET(边缘触发):Nginx 就是采用 ET 触发方式,只支持 no-b ...

  2. .Net Core 迁移之坑一 《WebAPI Get请求参数传入输入带有[]不识别问题》

    在Framwork 体系下 WebAPI项目 会有很多默认特性,例如:Get查询竟然支持三种数组查询方式 1.https://localhost:44390/api/values?status=1&a ...

  3. js监听文本框内容变化

    js监听文本框内容变化 原理很简单,就是在外部先声明一个用来记录input值的变量,然后每0.1秒比较这个值与input的值,如果发生改变,则运行自己的代码,同时改变变量.从而实现对input值改变的 ...

  4. Professional C# 6 and .NET Core 1.0 - Chapter 37 ADO.NET

    本文内容为转载,供学习研究.如有侵权,请联系作者删除. 转载请注明本文出处:Professional C# 6 and .NET Core 1.0 - 37 ADO.NET 译文:C# 6 与 .NE ...

  5. Html Meta标签记录

    记录学习过程中碰到的meta标签 方便今后查阅 X-UA-Compatible: 设置浏览器兼容 如<meta http-equiv="X-UA-Compatible" co ...

  6. box-shadow 内阴影

    1.盒子阴影样式单词:box-shadow 2.语法 代表边框间距靠左0 靠上0 和1px阴影范围 阴影颜色为黑色(#000),有inset 代表框内阴影 ,不带inset 代表框外阴影. 注意:bo ...

  7. Luogu 3537 [POI2012]SZA-Cloakroom

    背包. 首先考虑将所有询问离线按照$m$从小到大排序,然后把所有物品按照$a$从小到大排序,对于每一个询问不断加入物品. 设$f_i$表示在组成容量为$i$的背包的所有方案中$b$最小的一个物品的最大 ...

  8. 专题1-MMU-lesson2-深入剖析地址转化

    1.地址转化总体分析 level one fetch和level two fetch分为一级转换和二级转换. 由上图右边可以看出,首先通过TTB(Translation Table Base)寄存器找 ...

  9. Linux下安装memcache PHP扩展

    [root@centos memcache-2.2.4]# wget http://pecl.php.net/get/memcache-2.2.4.tgz [root@centos memcache- ...

  10. Jmeter跨线程组调用token

    BeanShell PostProcessor使用 1.正则提取token后添加:后置处理器-->BeanShell PostProcessor 2.BeanShell PostProcesso ...