C中的malloc/free与C++中的new/delete的用法与区别
1、先介绍malloc/free的用法:
原型函数: void *malloc(long NumBytes);
该函数分配了NumBytes个字节的内容,分配的空间是堆空间
malloc()根据用户所需分配内存的大小n (bytes)在“堆链表”(见未使用过得堆内存)里搜索。直到搜索到一个大于等于n字节的堆内存块为止。如果此堆内存块的大小刚好为n,则直接将首地址返回给用户;如果此内存块的大小大于n,则将此块堆内存分裂,将大于n部分的堆内存留在可用堆内存中,以“堆链表”的形式和其它未分配的堆内存发生联系。
如果整个堆链表所代表的堆内存块都没有大于等于n的堆内存块,系统将给“堆链表”链接一个更大的区域供其使用。要是这一步也失败了,malloc()函数就返回NULL给用户。
malloc()函数分配内存成功则返回可用堆内存块的首地址,若分配失败则返回空。在使用malloc()后一定要判断堆内存是否成功。若对内存分配未成功使用指针操作内存也会使程序出现异常。动态分配内存时要采取以下结构:
char *pL =NULL;
……
pL = (char *)malloc( sizeof(char) * size);
if(pL)
{
…
}
分配成功后,得到的堆内存首地址一定要保存,不然后来无法释放堆内存而造成内存泄露。而且不可使用未初始化的pL指向的内存块。
malloc函数只是完成内存的分配,但是并没有对分配的内存进行初始化设定,一般在进行malloc函数后面接着的语句就是内存空间初始化语句。
char * ps = (char*) malloc(sizeof(char)*15);
strcpy(ps, "hello world");
free函数与malloc()函数配对使用,释放malloc函数申请的动态内存。对于free(p)这句语句,如果p 是NULL 指针,那么free 对p 无论操作多少次都不会出问题。如果p 不是NULL 指针,那么free 对p连续操作两次就会导致程序运行错误。
为了防止以上错误,在使用free函数之前,应该先判断指针是否为NULL;
if(pL)
{
free(pL);
pL = NULL;
}
2、new和delete的用法
new和delete运算符是用于动态分配和撤销内存的运算符,解决了变量和对象在编译之前就要确定大小的问题,如数组必须大开小用,指针必须指向一个已经存在的变量或对象。
一、new用法
1.开辟单变量地址空间
使用new运算符时必须已知数据类型,new运算符会向系统堆区申请足够的存储空间,如果申请成功,就返回该内存块的首地址,如果申请不成功,则返回零值。
new运算符返回的是一个指向所分配类型变量(对象)的指针。对所创建的变量或对象,都是通过该指针来间接操作的,而动态创建的对象本身没有标识符名。
一般使用格式:
格式1:指针变量名=new 类型标识符;
格式2:指针变量名=new 类型标识符(初始值);
格式3:指针变量名=new 类型标识符 [内存单元个数];
说明:格式1和格式2都是申请分配某一数据类型所占字节数的内存空间;但是格式2在内存分配成功后,同时将一初值存放到该内存单元中;而格式3可同时分配若干个内存单元,相当于形成一个动态数组。例如:
1)new int; //开辟一个存放整数的存储空间,返回一个指向该存储空间的地址。int *a = new int 即为将一个int类型的地址赋值给整型指针a
2)int *a = new int(5) 作用同上,但是同时将整数空间赋值为5
2.开辟数组空间
对于数组进行动态分配的格式为:
指针变量名=new 类型名[下标表达式];
delete [ ] 指向该数组的指针变量名;
两式中的方括号是非常重要的,两者必须配对使用,如果delete语句中少了方括号,因编译器认为该指针是指向数组第一个元素的指针,会产生回收不彻底的问题(只回收了第一个元素所占空间),加了方括号后就转化为指向数组的指针,回收整个数组。
delete []的方括号中不需要填数组元素数,系统自知。即使写了,编译器也忽略。
请注意“下标表达式”不必是常量表达式,即它的值不必在编译时确定,可以在运行时确定。
一维: int *a = new int[100]; //开辟一个大小为100的整型数组空间
二维: int **a = new int[5][6]
三维及其以上:依此类推.
一般用法: new 类型 (初值)
二、delete用法
1. 删除单变量地址空间
int *a = new int;
delete a; //释放单个int的空间
2. 删除数组空间
int *a = new int[5];
delete []a; //释放int数组空间
区别:
0. 属性
new/delete是C++关键字,需要编译器支持。malloc/free是库函数,需要头文件支持。
1. 参数
使用new操作符申请内存分配时无须指定内存块的大小,编译器会根据类型信息自行计算。而malloc则需要显式地指出所需内存的尺寸。
2. 返回类型
new操作符内存分配成功时,返回的是对象类型的指针,类型严格与对象匹配,无须进行类型转换,故new是符合类型安全性的操作符。而malloc内存分配成功则是返回void * ,需要通过强制类型转换将void*指针转换成我们需要的类型。
3. 分配失败
new内存分配失败时,会抛出bac_alloc异常。malloc分配内存失败时返回NULL。
4. 自定义类型
new会先调用operator new函数,申请足够的内存(通常底层使用malloc实现)。然后调用类型的构造函数,初始化成员变量,最后返回自定义类型指针。delete先调用析构函数,然后调用operator delete函数释放内存(通常底层使用free实现)。
malloc/free是库函数,只能动态的申请和释放内存,无法强制要求其做自定义类型对象构造和析构工作。
5. 重载
C++允许重载new/delete操作符,特别的,布局new的就不需要为对象分配内存,而是指定了一个地址作为内存起始区域,new在这段内存上为对象调用构造函数完成初始化工作,并返回此地址。而malloc不允许重载。
6. 内存区域
new操作符从自由存储区(free store)上为对象动态分配内存空间,而malloc函数从堆上动态分配内存。自由存储区是C++基于new操作符的一个抽象概念,凡是通过new操作符进行内存申请,该内存即为自由存储区。而堆是操作系统中的术语,是操作系统所维护的一块特殊内存,用于程序的内存动态分配,C语言使用malloc从堆上分配内存,使用free释放已分配的对应内存。自由存储区不等于堆,如上所述,布局new就可以不位于堆中。
C中的malloc/free与C++中的new/delete的用法与区别的更多相关文章
- javascript中window与document对象、setInterval与setTimeout定时器的用法与区别
一.写在前面 本人前端菜鸟一枚,学习前端不久,学习过程中有很多概念.定义在使用时容易混淆,在此给向我一样刚踏入前端之门的童鞋们归纳一下.今天给大家分享一下js中window与document对象.se ...
- WordPress翻译中 __()、_e()、_x、_ex 和 _n 的用法及区别
编译函数 WordPress使用了下面几个函数来方便语言本地化. __() _e() _x() _ex() _n() 以上所列的函数是用来包含所需翻译的字符串的,根据字符串的不同参数和输出类型,需要使 ...
- SQL查询中in、exists、not in、not exists的用法与区别
1.in和exists in是把外表和内表作hash(字典集合)连接,而exists是对外表作循环,每次循环再对内表进行查询.一直以来认为exists比in效率高的说法是不准确的,如果查询的两个表大小 ...
- jquery easyui 中tab页添加其他页面,href与content的用法与区别
//tab页增加 function addPanel(name,url){ var dd = $('#tt').tabs('exists',name); if(dd){ $('#tt').tabs(' ...
- PHP中PHP $_POST和PHP $_REQUEST及PHP $_GET的用法及区别
笔者最近开始学习PHP语言大法,记录一下学习过程中遇到的知识点. 今天介绍的是php中有关 php $_post 和 php $_request 及 php $_get 的用法及区 ...
- 几个系统调用分析 glibc中的malloc调用和共享内存原理
本文主要分析内存以及I/O相关的系统调用和库函数的实现原理,根据原理给出在使用过程中需要注意的问题和优化的侧重点,本文涉及到的系统调用包括readahead,pread/pwrite,read/wri ...
- 浅谈C中的malloc和free
转自http://bbs.bccn.net/thread-82212-1-1.html非常感谢作者 浅谈C中的malloc和free 在C语言的学习中,对内存管理这部分的知识掌握尤其重要!之前对C中的 ...
- (转)浅谈C中的malloc和free
原帖及讨论:http://bbs.bccn.net/thread-82212-1-1.html 在C语言的学习中,对内存管理这部分的知识掌握尤其重要!之前对C中的malloc()和free()两个函数 ...
- C语言中内存分布及程序运行中(BSS段、数据段、代码段、堆栈)
BSS段:(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域.BSS是英文Block Started by Symbol的简称.BSS段属于静态内存分配. 数据段 : ...
随机推荐
- 通过$.ajax设置预加载动画加强用户体验
以前在jquery请求数据时,总喜欢用简洁的$.get与$.post提交数据,但有时发现由于网速的问题,有些时候网站加载js获得的数据会非常慢,于是就想能不能请求数据中间,给加载数据一个提示,增加用户 ...
- 【内核】Linux内核Initrd机制解析,内核更新步骤,grub配置说明
什么是Initrd initrd的英文含义是 boot loader initialized RAM disk,就是由boot loader初始化的内存盘.在 linux内核启动前, boot loa ...
- Lucas定理学习笔记(没有ex_lucas)
题目链接\(Click\) \(Here\) \(ex\_lucas\)实在是不能学的东西...简单学了一下\(Lucas\)然后打算就这样鸽着了\(QwQ\)(奶一口不可能考) 没什么复杂的,证明的 ...
- Grunt安装与环境配置
公司项目还没有前后端分离,而前端是使用node.js搭建起来的,现在需要自己动手开发,故学习下并做为记录防止以后忘记. grunt依赖node.js,所以在安装之前确保你安装了 Node.js.然后开 ...
- lucene之中文分词及其高亮显示(五)
中文分词:即换个分词器 Analyzer analyzer = new StandardAnalyzer();// 标准分词器 换成 SmartChineseAnalyzer analyze ...
- opencv: 排序
opencv提供了排序函数: sort和sorIdx , 其中sortIdx可以获取排序后的序号,比较方便: sortIdx原型: C++: void sortIdx(InputArray src, ...
- Elastic Stack之kibana使用
Elastic Stack之kibana使用 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 本篇博客数据流走向:FileBeat ===>Redis ===>log ...
- Python的命名空间及作用域
命名空间的分类 全局命名空间 是在程序从上到下被执行的过程中依次加载进内存的:放置了我们设置的所有变量名和函数名 局部命令空间 就是函数内部定义的名字:当调用函数的时候 才会产生这个名称空间 随着函数 ...
- 面向对象【day08】:异常处理-断言(七)
本节内容 1.概述 2.知识点回顾 3.断言 一.概述 python中断言,这个我是第一次听说到的,断言有什么用呢?断言就是做一些程序的检查工作,就是在执行之前需要做的一些检查,比如类似于安检一样,合 ...
- 如何优雅地使用Sublime Text3
此文非原创,出处见文章结尾. 一.Sublime Text 3插件安装 优雅使用Sublime Text,插件则是不可缺少的存在:而插件的备份就显得非常的重要(譬如:各平台同步:更换系统/电脑,迅速使 ...