delete 和 delete [] 的真正区别
来源:cbNotes 链接:http://blog.csdn.net/cbnotes/article/details/38900799
来源:公众号(c语言与cpp编程)
c++ 中对new
申请的内存的释放方式有 delete
和 delete[]
两种方式,到底这两者有什么区别呢?
我们通常从教科书上看到这样的说明:
- delete 释放new分配的单个对象指针指向的内存
- delete[] 释放new分配的对象数组指针指向的内存
那么,按照教科书的理解,我们看下下面的代码:
int *a = new int[10];
delete a; //方式1
delete[] a; //方式2
1. 针对简单类型 使用new分配后的不管是数组还是非数组形式内存空间用两种方式均可 如:
int *a = new int[10];
delete a;
delete[] a;
此种情况中的释放效果相同,原因在于:分配简单类型内存时,内存大小已经确定,系统可以记忆并且进行管理,在析构时,系统并不会调用析构函数。
它直接通过指针可以获取实际分配的内存空间,哪怕是一个数组内存空间(在分配过程中 系统会记录分配内存的大小等信息,此信息保存在结构体 _CrtMemBlockHeader 中,具体情况可参看 VC 安装目录下 CRTSRCDBGDEL.cpp)。
2. 针对类Class,两种方式体现出具体差异
当你通过下列方式分配一个类对象数组:
class A
{
private:
char *m_cBuffer;
int m_nLen;
`` public:
A(){ m_cBuffer = new char[m_nLen]; }
~A() { delete [] m_cBuffer; }
};
A *a = new A[10];
delete a; //仅释放了a指针指向的全部内存空间 但是只调用了a[0]对象的析构函数 剩下的从a[1]到a[9]这9个用户自行分配的m_cBuffer对应内存空间将不能释放 从而造成内存泄漏
delete[] a; //调用使用类对象的析构函数释放用户自己分配内存空间并且 释放了a指针指向的全部内存空间
所以总结下就是,如果 ptr
代表一个用new申请的内存返回的内存空间地址,即所谓的指针,那么:
delete ptr
代表用来释放内存,且只用来释放 ptr
指向的内存。delete[] rg
用来释放rg
指向的内存,!!还逐一调用数组中每个对象的destructor
!!
对于像int/char/long/int*/struct
等等简单数据类型,由于对象没有 destructor ,所以用 delete
和 delete []
是一样的!但是如果是 C++ 对象数组就不同了!
关于 new[]
和 delete[]
,其中又分为两种情况:
- (1)为基本数据类型分配和回收空间;
- (2)为自定义类型分配和回收空间;
对于 (1),上面提供的程序已经证明了delete[]
和delete
是等同的。但是对于 (2),情况就发生了变化。
我们来看下面的例子,通过例子的学习了解 C++ 中的 delete
和 delete[]
的使用方法
#include <iostream>
using namespace std;
class Babe
{
public:
Babe()
{
cout << "Create a Babe to talk with me" << endl;
}
~Babe()
{
cout << "Babe don't Go away,listen to me" << endl;
}
};
int main()
{
Babe* pbabe = new Babe[3];
delete pbabe;
pbabe = new Babe[3];
delete[] pbabe;
return 0;
}
结果是:
Create a babe to talk with me
Create a babe to talk with me
Create a babe to talk with me
Babe don't go away,listen to me
Create a babe to talk with me
Create a babe to talk with me
Create a babe to talk with me
Babe don't go away,listen to me
Babe don't go away,listen to me
Babe don't go away,listen to me
大家都看到了,只使用 delete
的时候只出现一个 Babe don’t go away,listen to me
,而使用 delete[]
的时候出现 3 个 Babe don’t go away,listen to me
。不过不管使用 delete
还是 delete[]
那三个对象的在内存中都被删除,既存储位置都标记为可写,但是使用 delete
的时候只调用了 pbabe[0]
的析构函数,而使用了 delete[]
则调用了 3 个 Babe
对象的析构函数。
你一定会问,反正不管怎样都是把存储空间释放了,有什么区别。
答:关键在于调用析构函数上。此程序的类没有使用操作系统的系统资源(比如:Socket、File、Thread
等),所以不会造成明显恶果。如果你的类使用了操作系统资源,单纯把类的对象从内存中删除是不妥当的,因为没有调用对象的析构函数会导致系统资源不被释放,如果是 Socket 则会造成 Socket 资源不被释放,最明显的就是端口号不被释放,系统最大的端口号是 65535 (216 _ 1,因为还有0),如果端口号被占用了,你就不能上网了,呵呵。如果 File 资源不被释放,你就永远不能修改这个文件,甚至不能读这个文件(除非注销或重启系统)。如果线程不被释放,这它总在后台运行,浪费内存和 CPU 资源。这些资源的释放必须依靠这些类的析构函数。所以,在用这些类生成对象数组的时候,用 delete[]
来释放它们才是王道。而用 delete
来释放也许不会出问题,也许后果很严重,具体要看类的代码了。
- 探寻ASP.NET MVC鲜为人知的奥秘(2):与Entity Framework配合,让异步贯穿始终
- Canvas 剪切图片
- 探寻ASP.NET MVC鲜为人知的奥秘(1):对LESS的支持
- Canvas 图片平铺设置
- Canvas 给图形绘制阴影
- State模式的经典应用场景:订单处理(c#实现)场景描述遇到问题解决问题走起
- ASP.NET SignalR 2.0入门指南介绍SignalRSignalR和WebSocket传输和回滚HTML5 传输协议Comet transports传输协议选择过程监测传输指定传输协议连接
- ASP.NET5之客户端开发:Grunt和Gulp构建工具在Visual Studio 2015中的高效的应用Grunt和Gulp使用Grunt准备项目配置NPM配置Grunt集成起来监测文件变化与V
- 有趣的算法(三)——Hash算法
- JavaScript中的数据类型
- Logistic回归算法及Python实现
- <script>元素在XHTML中的用法
- 有趣的算法(四)——一致性Hash算法模拟redis集群
- ASP.NET5 中静态文件的各种使用方式服务端的静态文件开启目录浏览呈现默认文件使用UseFileServer方法文件类型基于IIS的考虑最佳实践
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Python字符串三种格式化输出
- 你需要知道的Python代码规范性检查(pylint和flake8)
- Linux下安装python环境
- 【5】进大厂必须掌握的面试题-Java面试-spring
- Python 3.7 自动化接口测试简单实例
- 从 0 开始构建一个亿级请求的微服务架构
- ruby+cucumber+watir环境搭建
- Python常用模块os和shutil学习
- Python简单实现批量下载无版权图片
- Pycharm自动添加文件头注释和函数注释参数
- ClickHouse TTL for Columns and Tables
- Sentence-BERT详解
- 分布式文件系统(HDFS和FastDFS)
- Springboot集成JUnit5优雅进行单元测试
- 音视频相关开发库和资料