C++ STL 为我们提供了一套容器。在多数情况下,这套容器已足够让我们使用。所以,需要我们自己去用 new/new []/delete/delete [] 来管理内存的必要性并不是很大。此外,自己管理内存极容易导致程序出错。内存泄漏、堆遭到破坏这些事情都有可能发生。虽然各种编程 Tips 我们都熟稔于心,但真正在实际项目开发中遇到过的才令人印象深刻。

为什么不要自己管理内存?让我们重温这几条:
1. STL containers 已经经过良好设计,而且能满足大多数情况下的需求。
2. 只 new/new[] 未 delete/delete[] 或者 new/new[] 之后修改了得到的内存首地址,会导致内存泄漏。
3. 如果在一个类的实现中使用了 new/new[]、delete/delete[] ,而该类又没有设计良好的复制控制函数时,在标准容器中使用该类是危险的。

今天就结合实际项目经历强调一下第三点(很多书籍中也强调过这一点,但实际中未被坑过印象就不深刻啊)。
今天维护一个项目时,需要给4个通道的信号添加一步滤波处理。该滤波算法是一个同事做的,并以类的方式提供给我使用。下面是该类的大致代码:
class CFilter
{
public:
    CFilter(int len) {
        data_ = new double[len];
    }

~CFilter() {
        delete[] data_;
    }

// ... 省略算法实现部分。
private:
    double *data_;    
};
由于该类会根据每个通道的噪声特征调整类内部的一些参数,而每个通道的噪声特征都不一样,所以需要给每个通道都创建一个 CFilter 类型的对象。我是这样做的:
std::vector<CFilter> filters(4, 1000);
其中1000是传递给构造函数的参数。

这段代码是很危险的。因为标准容器的一些操作会涉及到元素的拷贝。而由于类的设计者未为 CFilter 类型提供拷贝构造函数和赋值构造函数(也就是未作任何复制控制),所以拷贝 CFilter 类型的对象时,其内部的 data_ 指针也会被拷贝,其后果可想而知。

在 VS2010 中,这段代码导致的错误就是进程堆被破坏,而且每次的出错地方都不一样。

解决方案:

1. 为类 CFilter 设计拷贝构造函数和复制构造函数,控制它的这些行为。

2. 把类 CFilter 类设计成 noncopyable 的。当然,这样可能就无法把 CFilter 类型的对象存储在标准容器中了。

慎用 new、delete的更多相关文章

  1. sql查询重复记录、删除重复记录方法大全

    查找所有重复标题的记录:SELECT *FROM t_info aWHERE ((SELECT COUNT(*)FROM t_infoWHERE Title = a.Title) > 1)ORD ...

  2. sql语句查询重复的数据

    查找所有重复标题的记录: SELECT *FROM t_info aWHERE ((SELECT COUNT(*)FROM t_infoWHERE Title = a.Title) > 1)OR ...

  3. oracle查找重复记录

    SELECT *FROM t_info aWHERE ((SELECT COUNT(*)          FROM t_info          WHERE Title = a.Title) &g ...

  4. SQL重复记录处理(查找,过滤,删除)

    SQL重复记录处理(查找,过滤,删除)     ID int    Title nvarchar(50)    AddDate datetime    数据  www.2cto.com     ID ...

  5. SQL查询重复记录、删除重复记录方法

    查找所有重复标题的记录:SELECT * FROM t_info a WHERE ((SELECT COUNT(*) FROM t_info WHERE Title = a.Title) > 1 ...

  6. MySQL中查询、删除重复记录的方法大全

    查找所有重复标题的记录: select title,count(*) as count from user_table group by title having count>1; SELECT ...

  7. oracle查找重复记录-转

    SELECT *FROM t_info aWHERE ((SELECT COUNT(*)          FROM t_info          WHERE Title = a.Title) &g ...

  8. oracle 归档日志总结

    Oracle 归档模式和非归档模式 归档模式和非归档模式 在DBA部署数据库之初,必须要做出的最重要决定之一就是选择归档模式(ARCHIVELOG)或者非 归档模式(NOARCHIVELOG )下运行 ...

  9. MySQL之——查询重复记录、删除重复记录方法大全

    查找所有重复标题的记录: SELECT * FROM t_info a WHERE ((SELECT COUNT(*) FROM t_info WHERE Title = a.Title) >  ...

  10. delect 删除

    delete ---整表数据删除 (慎用) delete  * from 表名; ---条件删除 delete  * from  表名  where  限制条件;

随机推荐

  1. 【多视图几何】TUM 课程 第2章 刚体运动

    课程的 YouTube 地址为:https://www.youtube.com/playlist?list=PLTBdjV_4f-EJn6udZ34tht9EVIW7lbeo4 .视频评论区可以找到课 ...

  2. 【算法学习】老算法,新姿势,STL——Heap

    “堆”是一个大家很熟悉的数据结构,它可以在\(O(log\;n)\)的时间内维护集合的极值. 这都是老套路了,具体的内部实现我也就不谈了. 我一般来说,都是用queue库中的priority_queu ...

  3. php CI框架

    CodeIgniter 是一个小巧但功能强大的 PHP 框架,作为一个简单而“优雅”的工具包,它可以为 PHP 程序员建立功能完善的 Web 应用程序.如果你是一个使用共享主机,并且为客户所要求的期限 ...

  4. nfs挂载出错:mount.nfs: access denied by server while mounting

    这个问题就是服务器不允许客户端去挂载,那么修改服务端的权限 $ sudo vi /etc/hosts.deny 文本末添加 ### NFS DAEMONS portmap: ALL lockd: AL ...

  5. java 多线程总结篇3之——生命周期和线程同步

    一.生命周期 线程的生命周期全在一张图中,理解此图是基本: 线程状态图 一.新建和就绪状态 当程序使用new关键字创建了一个线程之后,该线程就处于新建状态,此时它和其他的Java对象一样,仅仅由Jav ...

  6. afl入门学习

    一个简单的示例 安装afl wget http://lcamtuf.coredump.cx/afl.tgz tar xfz afl.tgz cd afl-xxx sudo make install 用 ...

  7. SQL Server中的快捷键

    新建查询:Ctrl + N 反撤销:Ctrl + Y 撤销:Ctrl + Z 查找:Ctrl + F 启动调试:Alt + F5 注释:Ctrl + K + C 取消注释:Ctrl + K + U 执 ...

  8. network出错

    1.更改IP之后,执行service network restart时出现 shutting down interface eth0:Device state :3(disconnected)的问题时 ...

  9. 003 Scipy库简介

    参考文档补充原本的文档: https://www.cnblogs.com/mrchige/p/6504324.html 一:原本的简单介绍 1.Scipy库 Scipy库是基于python生态的一款开 ...

  10. python脚本获取本机公网ip

    1.获取公网IP地址方式,访问:http://txt.go.sohu.com/ip/soip 2.python脚本实现: #!/usr/bin/python # -*- coding:utf8 -*- ...