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. IE安全系列之——RES Protocol

    IE安全系列之--RES Protocol res Protocol用于从一个文件里面提取指定资源.语法为:res://sFile[/sType]/sID 各Token含义: sfile:百分号编码. ...

  2. 2016.5.15——leetcode:Number of 1 Bits ,

    leetcode:Number of 1 Bits 代码均测试通过! 1.Number of 1 Bits 本题收获: 1.Hamming weight:即二进制中1的个数 2.n &= (n ...

  3. accept系统调用

    /* * For accept, we attempt to create a new socket, set up the link * with the client, wake up the c ...

  4. 关于mysql的wait_timeout参数 设置不生效的问题【转】

    关于wait_timeout 有一次去online set wait_timeout 的时候发现改了不生效,如下: mysql> show variables like 'wait_timeou ...

  5. python numpy数组中的复制问题

    vector = numpy.array([5, 10, 15, 20]) equal_to_ten_or_five = (vector == 10) | (vector == 5) vector[e ...

  6. Java Web 1-开发环境搭建(未完待续)

    Java Web包含什么?前台.后台,前台的HTML.JSP,后台的Servlet.(目前所知) 开发环境: JDK,MySQL,Tomcat,Eclipse @ Windows 10 说明:本文总结 ...

  7. git —— 多人协作(远程库操作)

    1.查看远程库信息 $ git remote 2.查看详细远程库信息 $ git remote -v 3.推送分支 $ git push origin 分支名 4.抓取分支 $ git checkou ...

  8. 题解 UVA10048 【Audiophobia】

    这是一道很神奇的题 什么都不卡,就卡c++11(所以评测时要换成c++). 怎么说呐,其实就是跑一个弗洛依德,求图上两点间最大权值最小的路径,输出最大权值最小. P.S.本题n很小,直接floyd变形 ...

  9. Laravel 程序架构设计思路:使用动作类

    当我们谈论到应用程序的架构的时候,经常会问到一个经典的问题,那就是"这段代码应该放在哪里比较好". 因为 Laravel 是一个相当灵活的框架,所以要回答这个问题其实没那么容易.我 ...

  10. 一步一步学习IdentityServer4 (5) .NETCore2.0 Swagger

    首先添加nuget: Swashbuckle.AspNetCore services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new ...