刷脸支付 正则表达式 jdbc Momentjs vue开发 vue基础教程 vue循环数组 找公司做网站 flink教程视频 jq选择子元素 linux 获取系统时间 java时间戳 wordpress本地建站 查看mysql密码 python加法 python新手教程 python学习文档 java的泛型 java数组输出 java方法调用 java的date java日期转时间戳 金山wps2003 typemonkey 制作字幕的软件 跳一跳脚本 咪咕客户端下载 电脑手机模拟器 extjs视频教程 win10有几个版本 ip地址转换器 奥法隐藏外观 电脑代码雨 js给标签添加属性 pr蒙版怎么用 神魔辅助 古特里克的杀生刀 骰子表情包 a1530是什么版本 ps蒙版抠图
当前位置: 首页 > 学习教程  > 编程语言

动态内存管理以及malloc,free和new,delete的区别

2020/8/11 19:13:33 文章标签:

为什么存在动态内存分配?
开辟空间的方式有两个特点:

  1. 空间开辟大小是固定的。
  2. 数组在申明的时候,必须指定数组的长度,它所需要的内存在编译时分配。

但是对于空间的需求,不仅仅是上述的情况。有时候我们需要的空间大小在程序运行的时候才能知道,那数组的编译时开辟空间的方式就不能满足了。 这时候就只能试试动态存开辟了。

C/C++中的内存分布

  1. 栈又叫堆栈,非静态局部变量/函数参数/返回值等等,栈是向下增长的。
  2. 内存映射段是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口创建共享共
    享内存,做进程间通信。(Linux课程如果没学到这块,现在只需要了解一下)
  3. 堆用于程序运行时动态内存分配,堆是可以上增长的。
  4. 数据段–存储全局数据和静态数据。
  5. 代码段–可执行的代码/只读常量。

动态内存函数的介绍

malloc和free

void* malloc(size_t size);
  1. 这个函数向内存申请一块连续可用的空间,并返回指向这块空间的指针。
  2. 如果开辟成功,则返回一个指向开辟好空间的指针。
  3. 如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查。
  4. 返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己来决定。
  5. 如果参数 size 为0,malloc的行为是标准是未定义的,取决于编译器。

C语言提供了另外一个函数free,专门是用来做动态内存的释放和回收的,函数原型如下:

void free (void* ptr);
  1. free函数用来释放动态开辟的内存。
  2. 如果参数 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的。
  3. 如果参数 ptr 是NULL指针,则函数什么事都不做。

malloc和free都声明在 stdlib.h 头文件中。

calloc

void* calloc(size_t num, size_t size);
  1. 函数的功能是为 num 个大小为 size 的元素开辟一块空间,并且把空间的每个字节初始化为0。
  2. 与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全0。

realloc

void* realloc(void* ptr, size_t size);
  1. realloc函数的出现让动态内存管理更加灵活。
  2. 有时会我们发现过去申请的空间太小了,有时候我们又会觉得申请的空间过大了,那为了合理的时候内存,
  3. 我们一定会对内存的大小做灵活的调整。那 realloc 函数就可以做到对动态开辟内存大小的调整。
  4. ptr 是要调整的内存地址
  5. size 调整之后新大小
  6. 返回值为调整之后的内存起始位置。
  7. 这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到 新的空间。

在c++中,有引用了新的动态内存开辟函数new,delete

new

void Test()
{
	// 动态申请一个int类型的空间
	int* ptr4 = new int;
 
	// 动态申请一个int类型的空间并初始化为10
	int* ptr5 = new int(10);
 
	// 动态申请10个int类型的空间
	int* ptr6 = new int[3];
 
	delete ptr4;
	delete ptr5;
	delete[] ptr6; 
}

申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用new[]和delete[]

new和delete是用户进行动态内存申请和释放的操作符,operator new 和operator delete是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间

operator new: 该函数实际通过malloc来申请空间,当malloc申请空间成功时直接返回;申请空间失败,尝试执行空 间不足应对措施,如果改应对措施用户设置了,则继续申请,否则抛异常。
operator delete: 该函数最终是通过free来释放空间的

new的原理

  1. 调用operator new函数申请空间
  2. 在申请的空间上执行构造函数,完成对象的构造

delete的原理

  1. 在空间上执行析**构函数,完成对象中资源的清理工作

  2. 调用operator delete函数释放对象的空间

new T[N]的原理

  1. 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对象空间的申
  2. 在申请的空间上执行N次构造函数

delete[]的原理

  1. 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理
  2. 调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释放空间

malloc/free和new/delete的区别

malloc/free和new/delete的共同点是:都是从堆上申请空间,并且需要用户手动释放。不同的地方是:

  1. malloc和free是函数,new和delete是操作符
  2. malloc申请的空间不会初始化,new可以初始化
  3. malloc申请空间时,需要手动计算空间大小并传递,new只需在其后跟上空间的类型即可
  4. malloc的返回值为void*, 在使用时必须强转,new不需要,因为new后跟的是空间的类型
  5. malloc申请空间失败时,返回的是NULL,因此使用时必须判空,new不需要,但是new需要捕获异常
  6. 申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new在申请空间
    后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理
  7. new/delete比malloc和free的效率稍微低点,因为new/delete的底层封装了malloc/free

关于内存分配的试题

int globalVar = 1;
static int staticGlobalVar = 1;
void Test()
{
 static int staticVar = 1;
 int localVar = 1;
 
 int num1[10] = {1, 2, 3, 4};
 char char2[] = "abcd";
 char* pChar3 = "abcd";
 int* ptr1 = (int*)malloc(sizeof (int)*4);
 int* ptr2 = (int*)calloc(4, sizeof(int));
 int* ptr3 = (int*)realloc(ptr2, sizeof(int)*4);
 free (ptr1);
 free (ptr3);
}
1. 选择题:
 选项: A.栈 B.堆 C.数据段 D.代码段
 globalVar在哪里?____ staticGlobalVar在哪里?____
 staticVar在哪里?____ localVar在哪里?____
 num1 在哪里?____
 
 char2在哪里?____ *char2在哪里?___
 pChar3在哪里?____ *pChar3在哪里?____
 ptr1在哪里?____ *ptr1在哪里?____
2. 填空题:
 sizeof(num1) = ____; 

 //C语言中动态内存管理方式
 malloc/calloc/realloc和free
 sizeof(char2) = ____; strlen(char2) = ____;
 sizeof(pChar3) = ____; strlen(pChar3) = ____;
 sizeof(ptr1) = ____;

本文链接: http://www.dtmao.cc/news_show_100088.shtml

附件下载

相关教程

    暂无相关的数据...

共有条评论 网友评论

验证码: 看不清楚?