关于malloc/free用法
和很多人一样,我一直觉得new/delete和malloc/free的用法很随意,直到我真正遇到了麻烦,才想着去好好区分一下。
(1)首先mallo函数原型void* malloc(size_t)。头文件stdlib.h。malloc 向系统申请分配指定size_t个字节的内存空间。返回类型是 void* 类型。void* 表示未确定类型的指针。C,C++规定,void* 类型可以强制转换为任何其它类型的指针。
int* p = (int *) malloc (sizeof(int)); 必须加(int* )强制转换,否则编译会报错。
(2)那么malloc是怎么工作的呢。malloc首先会将内存分成一个长的空闲链表,当你申请空间时,它会沿着链表找到一块足以满足要求的内存,将需要的大小分配给你,剩余的返回空余链表中,当你使用free函数释放空间时,它将这部分空间返回到链表中。这样有时候就会导致,空闲链会被切成很多的小内存片段,如果这时你申请一个大的内存片段,那么空闲链上可能没有可以满足要求的片段了。于是,malloc函数请求延时,并开始在空闲链上翻箱倒柜地检查各内存片段,对它们进行整理,将相邻的小空闲块合并成较大的内存块。如果无法获得符合要求的内存块,malloc函数会返回NULL指针,因此在调用malloc动态申请内存块时,一定要进行返回值的判断。(这一点好像大多数程序都不会注意)
if(p)
cout<<"Memory Allocated ";
else
cout<<"Not Enough Memory!";
(3)至于new到底干了些什么,我们先不追究,可以看看它和malloc的区别:
①申请的内存所在位置
new操作符从自由存储区(free store)上为对象动态分配内存空间,而malloc函数从堆上动态分配内存。自由存储区是C++基于new操作符的一个抽象概念,凡是通过new操作符进行内存申请,该内存即为自由存储区。而堆是操作系统中的术语,是操作系统所维护的一块特殊内存,用于程序的内存动态分配,C语言使用malloc从堆上分配内存,使用free释放已分配的对应内存。
②返回类型的区别
new分配成功时,返回的是对象类型的指针,无须进行类型转换,故new是符合类型安全性的操作符。而malloc内存分配成功则是返回void * ,需要通过强制类型转换将void*指针转换成我们需要的类型。
③内存分配失败时的返回值
new内存分配失败时,会抛出bac_alloc异常,它不会返回NULL,所以它不用额外去进行返回值判断,因为即便失败,也不会返回NULL;malloc分配内存失败时返回NULL。
④是否需要指定内存大小
使用new操作符申请内存分配时无须指定内存块的大小,编译器会根据类型信息自行计算,而malloc则需要显式地指出所需内存的尺寸。
⑤操作对象不同
malloc与free是C++/C 语言的标准库函数,new/delete 是C++的运算符。对于非内部数据类的对象而言,光用maloc/free 无法满足动态对象的要求。(比如string类型就只能用new,因为它不是内部数据类)对象在创建的同时要自动执行构造函数, 对象消亡之前要自动执行析构函数。由于malloc/free 是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加malloc/free。
⑤是否调用构造函数和析构函数
使用new操作符来分配对象内存时会经历三个步骤:
- 第一步:调用operator new 函数(对于数组是operator new[])分配一块足够大的,原始的,未命名的内存空间以便存储特定类型的对象。
- 第二步:编译器运行相应的构造函数以构造对象,并为其传入初值。
- 第三步:对象构造完成后,返回一个指向该对象的指针。
使用delete操作符来释放对象内存时会经历两个步骤:
- 第一步:调用对象的析构函数。
- 第二步:编译器调用operator delete(或operator delete[])函数释放内存空间。
⑥对数组的处理
C++提供了new[]与delete[]来专门处理数组类型:它会分别调用构造函数函数初始化每一个数组元素,释放对象时为每个对象调用析构函数。
A * ptr = new A[10];//分配10个A对象
delete [] ptr;
至于malloc,它并知道你在这块内存上要放的是不是数组,反正它就给你一块原始的内存,再给你个内存的地址就完事。所以如果要动态分配一个数组的内存,还需要我们手动自定数组的大小。
⑦new与malloc是否可以相互调用
operator new /operator delete的实现可以基于malloc,而malloc的实现不可以去调用new。
如果用free释放“new创建的动态对象”,那么该对象因无法执行析构函数而可能导致程序出错。如果用delete释放“malloc申请的动态内存”,理论上讲程序不会出错,但是该程序的可读性很差。
⑧是否可以被重载
opeartor new /operator delete可以被重载。标准库是定义了operator new函数和operator delete函数的8个重载版本,总之,我们知道我们有足够的自由去重载operator new /operator delete ,以决定我们的new与delete如何为对象分配内存,如何回收对象。
而malloc/free并不允许重载。
⑨ 能够直观地重新分配内存
使用malloc分配的内存后,如果在使用过程中发现内存不足,可以使用realloc函数进行内存重新分配实现内存的扩充。realloc先判断当前的指针所指内存是否有足够的连续空间,如果有,原地扩大可分配的内存地址,并且返回原来的地址指针;如果空间不够,先按照新指定的大小分配空间,将原有数据从头到尾拷贝到新分配的内存区域,而后释放原来的内存区域。
new没有这样直观的配套设施来扩充内存。
关于malloc/free用法的更多相关文章
- malloc函数用法
malloc函数用法 函数声明(函数原型): void *malloc(int size); 说明:malloc 向系统申请分配指定size个字节的内存空间.返回类型是 void* 类型.void* ...
- C语言中 malloc函数用法
一.malloc()和free()的基本概念以及基本用法: 1.函数原型及说明: void *malloc(long NumBytes):该函数分配了NumBytes个字节,并返回了指向这块内存的指针 ...
- c中malloc的用法
转自:http://blog.sina.com.cn/s/blog_966f8e8501010if7.html Malloc 向系统申请分配指定size个字节的内存空间.返回类型是 void* 类型. ...
- C语言malloc的用法及详解
#include <stdio.h> #include <stdlib.h> void freem(int* p){ #include <stdio.h> #inc ...
- c/c++动态分配内存和malloc的使用
c/c++动态分配内存 为什么需要动态分配内存 ---很好的解决的了传统数组的4个缺陷 动态内存分配举例 ---动态数组的构造 使用动态数组的优点: 1. 动态数组长度不需要事先给定: 2. ...
- 数据结构基础——指针及动态内存分配(malloc)
一.指针 C语言中的指针是一种数据类型,比如说我们用int *a;就定义了一个指针a,它指向一个int类型的数.但是这个指针是未初始化的,所以,一般的,我们都在创建指针时初始化它,以免出错,在还不吃的 ...
- 内存分配malloc函数注意事项。
malloc的全称是memory allocation,中文叫动态内存分配,用于向系统申请分配指定字节的内存空间 原型:extern void *malloc(unsigned int num_byt ...
- new与delete,malloc与free
1.new_delete与malloc_free ❶malloc/free: malloc原型: void *malloc(long NumBytes) 该函数分配了NumBytes个字节,并返回了指 ...
- malloc在函数内分配内存问题
malloc函数用法可参考:C语言中 malloc函数用法 及 malloc函数 代码: void fun(char * p) { p=(); } void main() { char *p; fun ...
随机推荐
- Flask之静态文件处理
静态文件的处理 推荐 from flask import Flask,render_template app = Flask(__name__,template_folder='templates', ...
- 【AtCoder Beginner Contest 181】A~F题解
越学越菜系列 于2020.11.2,我绿了(错乱) A - Heavy Rotation 签到题,奇数Black,偶数White. code: #include<bits/stdc++.h> ...
- java虚拟机入门(一)-jvm基础
转行学java之前,总是听着大佬们说着java像个渣男一样可以跨平台,一次编译到处运行,瞬间,我就坚定了学java的信念,哎呀妈呀,得劲.真的学java之后,好像渣男也不是那么好学的,尤其这货的必杀技 ...
- 解决 browser-sync start --server --files 文件不能同步的问题!
解决 browser-sync start --server --files 文件不能同步的问题! 请看我的源命令: browser-sync start --server --file 'test2 ...
- Soul API 网关源码解析 03
目标 使用 soul 代理 dubbo 服务 dubbo 服务如何注册到网关的? dubbo 插件是如何工作的? 理清 http --> 网关--> dubbo provider 整条链路 ...
- elasticsearch从开始到永久
0.学习目标 独立安装Elasticsearch 会使用Rest的API操作索引 会使用Rest的API查询数据 会使用Rest的API聚合数据 掌握Spring Data Elasticsearch ...
- Makefile 描述的是文件编译的相关规则,它的规则主要是两个部分组成,分别是依赖的关系和执行的命令 PHONY伪目标实践
Makefile的工作流程 http://c.biancheng.net/view/7091.html Makefile文件是什么? 我们教程主要是讲的是 Makefile .很多 Linux(Uni ...
- Spring Boot中的静态资源文件
Spring Boot中的静态资源文件 1.SSM中的配置 2.Spring Boot 中的配置 2.1 整体规划 2.2 源码解读 2.3 自定义配置 2.3.1 application.prope ...
- Grafana+Influxdb+Telegraf监控mysql
Grafana+Influxdb+Telegraf监控mysql 一.安装 1.1安装Grafana+influxdb+telegraf 1.2启动服务,添加开机启动 1.3查看grafana界面 二 ...
- JDBC的操作步骤和实例()
加载JDBC驱动程序 提供JDBC连接的URL 创建数据库的连接 创建一个Statement 执行SQL语句 处理结果 关闭JDBC对象 实例JdbcUtils 创建一个JDBC程序包含7个步骤: 1 ...