动态内存管理:malloc和free以及new和delete的联系与区别

动态内存管理:malloc和free以及new和delete的联系与区别

一、 C/C++中程序内存区域划分:

  1. 内核空间:Linux系统对自身进行了划分,一部分核心软件独立于普通应用程序,运行在较高的特权级别上,它们驻留在被保护的内存空间上,拥有访问硬件设备的所有权限,Linux将此称为内核空间。
  2. 栈:又叫堆栈,非静态局部变量和函数参数及返回值都在栈上存储,栈是重上往下增长的。
  3. 内存映射段:是高效的I/O映射方式,用于装载一个共享的动态内存库,用户可以使用系统接口创建共享共享内存,做进程间通信,
  4. 堆:用于程序运行时动态分配内存,堆是从下往上增长的。
  5. 数据段:存储静态数据和全局变量。
  6. 代码段:可执行时的代码和只读常量。

具体如下图:
在这里插入图片描述
二、C语言中动态分配内存管理方式:

  1. malloc:

原型:

void *malloc(int byte_size);

作用:动态开辟byte_size个字节的内存空间,不进行初始化,返回指向此内存的指针,此指针所指数据类型没有确定,需要强转。

举例:

int *p=(int *)malloc(5*sizeof(int));

例解:动态开辟5*4=20个字节大小的空间,返回空间首地址指针并强转为int *型后赋予指针变量p。

注意:malloc只开辟空间,不初始化,即只将此空间由未占用状态变为已占用状态,空间内存储的具体数据未指定改变。函数返回值是空间首地址,上例中赋给了p变量。

2.calloc:

原型:void *calloc(int n,int type_byte_size);

作用:动态开辟n*type_byte_size个字节,将每个字节均初始化为ascii码0,返回指向此内存的指针,此指针所指数据类型没有确定,需要强转。

举例:int *p=(int *)calloc(5,sizeof(int));

例解:动态开辟5*4=20个字节大小的空间,其中每个字节均赋初值0,返回空间首地址指针并强转为int *型后赋予指针变量p。

注意:calloc在malloc的基础上将空间按字节初始化为ascii码0,且其参数有两个,两参数之积为空间总字节数。

  1. realloc:

原型:

void *realloc(void *p,int byte_size);

作用:对空间进行调整,若p为空,则该函数与malloc相同,若p所指空间连续大小(单位字节)大于byte_size,则从首地址开始连续地扩充开辟p所指空间至byte_size字节,不对空间再次赋值,将空间地址指针返回;若p所指空间连续大小小于byte_size,则新开辟byte_size字节大小的空间,将p指向的空间内的数据复制进新空间,之后释放p所指空间(此时p为NULL),返回指向新空间的指针,此指针所指数据类型没有确定,需要强转。

举例:

int *p=(int *)calloc(5,sizeof(int));
  p =(int*)realloc(p,10*sizeof(int));

例解:首句中p为5*4=20字节的空间指针并按字节初始化为ascii码0,(int )强转后才限定了指向空间的每个元素为int型。后句将p所指空间扩充为104=40字节的空间指针,未对其二次赋值,故此时p[0]p[4]为0,p[5]p[9]未初始化。

注意:realloc的第一个参数必须是动态开辟的地址,不能是静态定义的数组的地址,结构体数组也不行。

4.free:
C 库函数 void free(voidptr)* 释放之前调用 calloc、malloc 或 realloc 所分配的内存空间 。
ptr-- 指针指向一个要释放内存的内存块,该内存块之前是通过调用 malloc、calloc 或 realloc 进行分配内存的。如果传递的参数是一个空指针,则不会执行任何动作。
该函数不返回任何值。
下面的实例演示了 free() 函数的用法:

 #include <stdio.h>
 int main()
{   
    char *str;    /* 最初的内存分配 */   
    str = (char *) malloc(15);   
    strcpy(str, "jikexueyuan");   
    printf("String = %s,  Address = %un", str, str);   /* 重新分配内存 */   
    str = (char *) realloc(str, 25);   
    strcat(str, ".com");  
     printf("String = %s,  Address = %un", str, str);   /* 释放已分配的内存 */   
    free(str);   return(0);
    }

让我们编译并运行上面的程序,这将产生以下结果:

String = jikexueyuan, Address = 355090448String = jikexueyuan.com, Address = 355090448

三、C++内存管理方式:

  1. new/delete操作内置类型:
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[]操作符。
2. new/delete操作自定义类型:

class Test
{
public:
Test()
: _data(0)
{
cout<<"Test():"<<this<<endl;
}
~Test()
{
cout<<"~Test():"<<this<<endl;
}
private:
int _data;
};
void Test2()
{
// 申请单个Test类型的空间
Test* p1 = (Test*)malloc(sizeof(Test));
free(p1);
// 申请10个Test类型的空间
Test* p2 = (Test*)malloc(sizoef(Test) * 10);
free(p2);
}
void Test2()
{
// 申请单个Test类型的对象
Test* p1 = new Test;
delete p1;
// 申请10个Test类型的对象
Test* p2 = new Test[10];
delete[] p2;
}

注意:在申请自定义类型空间时,new会调用类的构造函数,delete会调用类的析构函数,malloc和free不会调用。

  1. new和delete的实现原理:

a、如果申请的是内置空间

那么new/delete,malloc/free就没有太大区别。不同的地方主要有如果malloc申请空间失败,则会返回NULL,所以在用之前要进行判空处理。而new操作符申请空间时,如果失败,就会优先进行调整,若没有调整操作,就会抛出异常。

b、如果申请的是自定义空间:
new的原理为:
首先调用operator new函数申请一个空间,而operator new函数则采用循环的方式,用malloc来进行申请空间,若申请空间失败,就会优先进行调整操作,直到申请成功,若没有调整操作,就会抛出异常。(注意此时并没有申请成功,只是相当于申请了以个大小相同的空间而已,此时该对象是不完整的)所以最后进行的操作是在申请的空间上执行类的构造函数,完成对象的构造。
delete的原理为:
首先为了防止内存泄漏,在该空间上执行类的析构函数,完成对象资源清理工作,最后调用operator delete函数,释放该对象的空间。
new[N]的原理为:
调用operator new[] 函数,而在operator new[]中实际调用operator new函数完成对N个对象空间的申请操作,最后在申请的空间上执行N次构造函数,完成对N个对象的申请。

delete[]原理为:
在申请的空间上执行N次析构函数,完成对N个对象的资源清理工作,最后在调用operator delete[] 函数,而在operator delete[]函数中实际调用operator delete函数完成对N个对象空间的释放回收操作。

四、malloc/free与new/delete的区别:

malloc/free new/delete
是标准库内的函数 是关键字,不是函数
malloc申请的空间不会初始化 new出来的空间可以初始化
malloc申请空间时,需要手动计算申请空间的大小并传递 new不需要,只需在后面跟空间的类型
malloc的返回值为void*,所以在使用时要进行强转操作 new后跟的就是空间的类型
malloc申请空间失败会返回NULL,所以使用时需要判空 new申请空间失败会抛出异常
在申请自定义空间时,malloc/free只负责开辟空间,和释放空间,不会调用构造函数和析构函数 new会在申请空间后调用构造函数完成对象的初始化,delete会在释放空间前调用析构函数完成资源清理工作。
发布了49 篇原创文章 · 获赞 15 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/wolfGuiDao/article/details/102692530