条目七《如果容器中包含了通过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 要拷贝的宿主机文件或目录 容器名称:容器文件或目 ...
随机推荐
- 数据仓库-数据采集-ETL漫谈
数据仓库之ETL漫谈ETL,Extraction-Transformation-Loading的缩写,中文名称为数据抽取.转换和加载.大多数据仓库的数据架构可以概括为:数据源-->ODS(操作型 ...
- spring quartz 配置多个定时任务
1.配置文件-quartz-1.7.3jar spring版本为3.1.3jar <?xml version="1.0" encoding="UTF-8&quo ...
- hibernate 框架的简单使用
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuratio ...
- Cannot connect to the Docker datemon at tcp://0.0.0.0:2375 is the docker daemon runing?
一.系统环境: 在Windows 7 64位上,采用Vmware workstation 12安装了CenOS7.5 64位. 二.问题 在CentOS7.5里安装了Docker,启动docker服务 ...
- 在Ubuntu安装Tomcat7.0及开机自动运行
在Ubuntu安装Tomcat7.0及开机自动运行 1.安装装Tomcat7.0 一般都是绿色版的,下载一个tomcat7.0解开到指定的目录上即可 然后进入tomcat目录的bin文件夹,执行 su ...
- c语言实践:求两个数的最大公约数
我的思路是这样的:比如12和16这两个数.先理解一下概念,什么叫最大公约数.就是12有很多个因数,16也有很多个因数,这两堆因数中有一些重合的因数,在这些重合的因数中找到那个最大的.那么最大公约数一定 ...
- C# 用代码返回上一页
若我们在后台.cs文件中想做到让浏览器返回上一页,我们可以在.cs代码中这样写 Page.ClientScript.RegisterStartupScript(Page.GetType(), &quo ...
- eclipse——执行Maven命令
右键pom.xml文件 点击 m2 Maven build... 输入要执行的命令,点击Run 控制台会打印maven运行过程
- hdu 4269 Defend Jian Ge
#include <cctype> #include <algorithm> #include <vector> #include <string> # ...
- App性能测试工具使用说明-MobilePerformance
一. 环境搭建 安装Android SDK 1.6或者1.7版本均可,建议1.7,环境变量的配置,Java SDK的安装很简单,不赘述了. 安装SDK 1.安装Android SDK: 2.安装完毕后 ...