慎用 new、delete

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 类型的对象存储在标准容器中了。

时间: 2024-12-16 20:04:57

慎用 new、delete的相关文章

sql语句查询重复的数据

查找所有重复标题的记录:SELECT *FROM t_info aWHERE ((SELECT COUNT(*)FROM t_infoWHERE Title = a.Title) > 1)ORDER BY Title DESC一.查找重复记录1.查找全部重复记录Select * From 表 Where 重复字段 In (Select 重复字段 From 表 Group By 重复字段 Having Count(*)>1)2.过滤重复记录(只显示一条)Select * From HZT Whe

oracle查找重复记录

SELECT *FROM t_info aWHERE ((SELECT COUNT(*)          FROM t_info          WHERE Title = a.Title) > 1)ORDER BY Title DESC 一.查找重复记录 1.查找全部重复记录 Select * From 表 Where 重复字段 In (Select 重复字段 From 表 Group By 重复字段 Having Count(*)>1) 2.过滤重复记录(只显示一条) Select *

运维人员如何最大限度避免误删除文件

很多工作的网友对运维工作的定位,背黑锅的,“黑锅侠”! 企业运维工作中50%以上的故障都是因内部人员管理失误造成的,“某程”就是个典型例子. 如果规范工作中的一举一动,就会不断的犯错,最后导致所有的功劳都变成徒劳. 那么老男孩老师在10多年的运维工作中是如何高效运维,不让运维成为黑锅侠的呢? 今天给大家分享一些简单但可以有效的防止误删数据的小技巧: 1.修改或删除数据前请务必备份,最好有异机备份,修改配置等先提交版本管理系统在发布到线上. 2.运维新手删除应使用mv命令替代rm命令,无用的文件不

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

查找所有重复标题的记录:SELECT * FROM t_info a WHERE ((SELECT COUNT(*) FROM t_info WHERE Title = a.Title) > 1) ORDER BY Title DESC一.查找重复记录1.查找全部重复记录Select * From 表 Where 重复字段 In (Select 重复字段 From 表 Group By 重复字段 Having Count(*)>1)2.过滤重复记录(只显示一条)Select * From HZ

oracle查找重复记录-转

SELECT *FROM t_info aWHERE ((SELECT COUNT(*)          FROM t_info          WHERE Title = a.Title) > 1)ORDER BY Title DESC 一.查找重复记录 1.查找全部重复记录 Select * From 表 Where 重复字段 In (Select 重复字段 From 表 Group By 重复字段 Having Count(*)>1) 2.过滤重复记录(只显示一条) Select *

数据库操纵

一. 查找重复记录 1. 查找全部重复记录 Select * From 表 Where 重复字段 In (Select 重复字段 From 表 Group By 重复字段 Having Count(*)>1) 2. 过滤重复记录(只显示一条) Select * From HZT Where ID In (Select Max(ID) From HZT Group By Title) 注:此处显示ID最大一条记录 二. 删除重复记录 1. 删除全部重复记录(慎用) Delete 表 Where 重

(八)Hibernate的一对多关联关系

一.概述 例如,以客户(Customer)和订单(Order)为例,一个客户能有多个订单,一个订单只能有一个客户. 从Customer到Order是一对多关联,在java类中的面向对象设计应该一个Customer对象包含多个Order对象,因此应该定义一个集合,来包含所有的Order对象. 从Order到Customer是多对一关联,在java类中设计每个Order对象需要关联一个Customer对象,因此Order类中应该定义一个Cutomer类型的属性,来引用关联的customer对象. 但

delect 删除

delete ---整表数据删除 (慎用) delete  * from 表名; ---条件删除 delete  * from  表名  where  限制条件; 原文地址:https://www.cnblogs.com/topzhangRX/p/10134675.html

oracle中delete drop truncate的用法和区别

数据库的运维中,经常会遇到delete drop truncate的操作,那么如何去把握它们的用法和区别呢? 比如当数据库空间爆满,已经增长到存储空间单个存储文件的最大值32G.你需要通过一些办法释放掉表空间或者扩容表空间来解决问题. 一般当系统中大量使用分区表,而针对分区表清除数据,是不会释放表空间的,必须把分区drop掉,才会释放空间. 下面我们具体了解一下这三个命令: 一.delete 1.delete是DML,执行delete操作时,每次从表中删除一行,并且同时将该行的的删除操作记录在r