条目七《如果容器中包含了通过new操作创建的指针,切记在容器对象析构前将指针delete掉》
如果容器中包含了通过new操作创建的指针,切记在容器对象析构前将指针delete掉
在STL中容器是智能的,可以在容器销毁时自动调用容器里对象的析构函数来销毁容器存储的对象。
STL的容器虽然比较智能,但是没有智能到可以自动销毁new出来的指针对象。
所以在使用STL中的容器时,如果保存的是mew出来的对象的指针。如果在容器销毁之前没有把new出来的对象释放,会造成内存泄露。
解决方法版本一:
void doSomething()
{
vector<Widget*> vwp;
...
for (vector<Widget*>::iterator i = vwp.begin();i != vwp.end(),++i)
{
delete *i;
}
}
这种手工释放容器里new的对象不太可靠,菲异常安全的。如果在delete的时候爆出异常,那么还是会引起内存泄露。
解决方法二:
template<typename T>
struct DeleteObject : public unary_function<const T*, void>
{
void operator()(const T* ptr) const
{
delete ptr;
}
};
这是一个函数对象。
void doSomething()
{
... // 同上
for_each(vwp.begin(), vwp.end(), DeleteObject<Widget>);
}
手动销毁new出来的对象
使用函数对象的方式,可以保证对象的安全销毁完,虽然在调用时需要指明函数对象类型,实现了适配器作用,但是这种方法需要公有继承,有个特殊情况,就是STL的string。
class SpecialString: public string { ... };
void doSomething()
{
deque<SpecialString*> dssp;
...
for_each(dssp.begin(), dssp.end(),DeleteObject<string>());// 虚析构函数的基类
}
string是没有虚析构函数的,所以在作为基类时,在这个对象使用完析构时,会找不到对应的析构函数,这时的行为是未知的。
解决方法三:
struct DeleteObject {
template<typename T> // 模板化加在这里
void operator()(const T* ptr) const
{
delete ptr;
}
}
void doSomething()
{
deque<SpecialString*> dssp;
for_each(dssp.begin(), dssp.end(),DeleteObject());
}
把模板化放在类里面,重载()操作符前,由编译器自动判断调用者的类型,这样就可以避免公有继承这一步操作,也就实现了通用。但是却丢弃了可适配的能力。
最优的解决方法:
void doSomething()
{
typedef boost::shared_ ptr<Widget> SPW;
vector<SPW> vwp;
for (int i = 0; i < SOME_MAGIC_NUMBER; ++i)
vwp.push_back(SPW(new Widget)); // 从一个Widget建立SPW,然后进行一次push_back
...
// 使用vwp
}
使用boost里的shared_ptr智能指针,通过其的自动计算引用计数的实现来,在使用STL容器保存new出来的对象指针时,超出作用域范围自动销毁智能指针里的对象,实现安全可靠高效的解决内存泄露方案。
总的来说,在使用STL容器存储new出来的对象的指针时,需要注意对象的析构销毁步骤。这一步是需要我们自己来管理的。
条目七《如果容器中包含了通过new操作创建的指针,切记在容器对象析构前将指针delete掉》的更多相关文章
- 7 -- Spring的基本用法 -- 5... Spring容器中的Bean;容器中Bean的作用域;配置依赖;
7.5 Spring容器中的Bean 7.5.1 Bean的基本定义和Bean别名 <beans.../>元素是Spring配置文件的根元素,该元素可以指定如下属性: default-la ...
- 【String注解驱动开发】如何按照条件向Spring容器中注册bean?这次我懂了!!
写在前面 当bean是单实例,并且没有设置懒加载时,Spring容器启动时,就会实例化bean,并将bean注册到IOC容器中,以后每次从IOC容器中获取bean时,直接返回IOC容器中的bean,不 ...
- 在 docker 容器中捕获信号
我们可能都使用过 docker stop 命令来停止正在运行的容器,有时可能会使用 docker kill 命令强行关闭容器或者把某个信号传递给容器中的进程.这些操作的本质都是通过从主机向容器发送信号 ...
- 隔离 docker 容器中的用户
笔者在前文<理解 docker 容器中的 uid 和 gid>介绍了 docker 容器中的用户与宿主机上用户的关系,得出的结论是:docker 默认没有隔离宿主机用户和容器中的用户.如果 ...
- 在Docker容器中搭建MXNet/Gluon开发环境
在这篇文章中没有直接使用MXNet官方提供的docker image,而是从一个干净的nvidia/cuda镜像开始,一步一步部署mxnet需要的相关软件环境,这样做是为了更加细致的了解mxnet的运 ...
- docker容器中的peewee如何连接已有的容器中的数据库
首先,两个容器必须是在同一网络下,有2个办法. 一个是在同一个docker-compose.yml文件下使用links参数,比如: version: '3' services: redis: imag ...
- spring在IoC容器中装配Bean详解
1.Spring配置概述 1.1.概述 Spring容器从xml配置.java注解.spring注解中读取bean配置信息,形成bean定义注册表: 根据bean定义注册表实例化bean: 将bean ...
- docker容器中解决出现:^H^H^H^H
docker容器中解决出现:^H^H^H^H 环境:docker容器是debain系统 解决: 把stty erase ^H 添加到.bash_profile中 vim /etc/profile st ...
- Docker拷贝宿主机与容器中的文件
如果我们需要将宿主机文件拷贝到容器内可以使用 docker cp 命令,也可以将文件从容器内拷贝到宿主机 将宿主机文件拷贝到容器内 docker cp 要拷贝的宿主机文件或目录 容器名称:容器文件或目 ...
随机推荐
- easyui之datagrid之formatter(后台传递常量自动转换值)
1,datagrid之formatter formatter格式化函数有三个参数: value:字段值(一般为后台传递给前台的值): row:当前行数据: index:当前行索引. return值是显 ...
- springBoot集成 quartz动态定时任务
项目中需要用到定时任务,考虑了下java方面定时任务无非就三种: 用Java自带的timer类.稍微看了一下,可以实现大部分的指定频率的任务的调度(timer.schedule()),也可以实现关闭和 ...
- oracle 通过序列实现某字段自增
-- 创建表 create table items( id int primary key, name ) not null, price int not null, detail ), pic ), ...
- spring 框架jdbc连接数据库
user=LF password=LF url=jdbc:oracle:thin:@localhost:1521:orcl driver=oracle.jdbc.driver.OracleDriver ...
- Ubuntu14.04(64位)下gcc-linaro-arm-linux-gnueabihf交叉编译环境搭建
1. 下载 gcc-linaro-arm-linux-gnueabihf-4.9.tar.gz 下载地址参考:http://blog.csdn.net/lg1259156776/article/det ...
- ESP8266文档阅读2A-SDK-Espressif IoT SDK 使用手册v1.0.1.pdf
2A-SDK-Espressif IoT SDK 使用手册v1.0.1.pdf 1.前言 本⽂文主要介绍基于ESP8266物联⺴⽹网模块的SDK相关使⽤用⽅方法,包括开发⼯工具使⽤用以及SDK软件包架 ...
- ESP8266-iot-2
1.SDK概述 复制相关的工程文件到HelloWorld里面 要在版本esp8266_nonos_sdk_v2.0.0_16_07_19上面开发,那么就要复制相应文件 然后打开IDE 导入HelloW ...
- [GO]结构体及普通变量初始化
结构体是一种聚合的数据类型,它是由一系列相同类型或者不同类型的数据构成的数据集合,每个数据称为结构体的成员 1.结构体的初始化 package main import "fmt" ...
- Detailed ASP.NET MVC Pipeline
Posted By : Shailendra Chauhan, 27 Jan 2014 P.NET MVC is an open source framework built on the top o ...
- python3 tkinter 获取输入字符串长度
python 3 获取输入字符长度 #-*- coding:utf-8 -*- from tkinter import * from tkinter import messagebox def ge ...