浅谈new/delete

在C语言的学习中,我们知道动态内存开辟是使用malloc函数来进行开辟一段连续的空间,释放则是用free来进行释放,而学习了C我们知道,在C中开辟内存是使用new,释放则也与之对应的delete,下面我们就来说说malloc/free与new/delete之间的区别以及底层实现原理

回顾

在C语言库中函数原型如下

#include <stdlib.h>
void *malloc(size_t size);
void free(void *ptr);

malloc/free使用

int *p = (int*)malloc(sizeof(int));     //指向整型的指针p指向一个大小为4字节的内存的地址
if(p == NULL)                           //使用之前一定要判断释放申请成功
{
    printf("application memory error");
}
free(p);    //释放

与之还以两个函数

void *calloc(size_t nmemb, size_t size);
void *realloc(void *ptr, size_t size);
void *reallocarray(void *ptr, size_t nmemb, size_t size);

calloc 函数和malloc的区别就是申请好空间会初始化成0,另外calloc函数在使用时需要传入元素个数和元素字节大小

recalloc函数用于修改一个原先已经分配好的内存块的大小,可以使一块内存扩大或缩小,如果扩大内存,则原来的内存块保持不变,在内存尾部增加新的内存块,且不进行初始化。如果缩小内存,则原来内存块从尾部进行删减。如果原先的内存块无法扩充,则新开辟一块内存,并复制原先的内存的内容,原先内存块失效无法再进行访问。

new/delete使用

int *p = new int;   //在自由存储区中分配创建了一个整形对象,并返回一个指向该对象的地址来初始化指针p
int *p = new int(); //对指针p指向的地址的值进行了初始化为0
int *P = new int(1024);//初始化为1024

当动态创建的对象用完后必须释放内存,避免造成内存泄漏,可以用delete来完成,new和delete是成对使用的,如下命令释放p指向的int型对象所占用的内存空间:

delete p
p = NULL;

C++中允许动态创建const对象

const int  *p=new const int(1024);  //动态创建的const对象必须进行初始化,并且进行初始化后的值不能再改变。

new[]/delete[]使用

当创建一个动态数组对象和进行内存释放时,执行以下语句:

int *p=new int[];               //指针p所指向的数组未初始化
int *p=new int[n];             //指针p指向长度为n的数组,未初始化
int *p=new int[]();            //指针p所指向的地址初始化为0
delete [] p;                   //回收p所指向的数组

区别及原理

new/delete原理

首先我们查看new/delete底层是如何实现的

 

通过上面的图我们不难看出其实new并不直接开辟空间,它也是通过operator new 来获取内存的,而operator new 实质上还是调用malloc来开辟空间的。同样的道理,delete也不是直接释放空间。

new[]/delete[]原理

上面理解了new/delete之后再来看new[]/delete[]也非常容易了,其实原理是一样的,当使用new[]/delete[]也是调用new/delete来实现的。

A* p = new A[10];
delete[] p;

delete[] 实际做了这样几件事:

  • 一次调用p指向对象数组中的每个对象的析构函数,一共10次
  • 调用operator delete,它将在调用operator delete
  • 底层free执行operator delete表达式

稍作总结

  1. operator new/operator delete,operator new[]/operator delete[],malloc/free等用法一样
  2. 它们只负责分配空间/释放空间,不会调用对象构造函数,析构函数来初始化和清理对象
  3. 实际operator new和operator delete 是对malloc和free的一层封装

注意点
可能你对上面还有些许疑惑,下面的解释可能会解开你的疑惑

Array* p = new Array[10];
delete[] p;

执行这两条语句的时候实际上调用operator new分配大小为10*sizeof(Array)+4空间,其中多的四个字节空间用于存放N(10)这个数字以便于delete中调用析构函数析构对象(调用析构函数的次数),空间申请好了之后调用构造函数创建对象。delete[] p执行的时候首先取N(10)对象个数,然后调用析构函数析构对象,最后用operator delete[]函数释放空间。

区别

先来一个问题
有了malloc/free为何还要new/delete ?

       因为malloc和free无法满足对动态对象的要求:在创建对象的同时自动调用构造函数,对象销毁时自动调用析构函数。由于malloc/free是库函数不是操作符,不在编辑器的权限之内,而C++中需要需要new操作符来自动调用构造函数来申请空间初始化,以及需要一个能够完成清理与释放内存的delete操作符

共同点: malloc/free new delete都是从堆上申请空间,并且需要用户手动释放
不同点:
1.malloc和free是函数,new delete是操作符
2.malloc申请空间不会初始化,new 可以初始化
3.malloc申请空间时需要计算所需的空间大小并传递,new只需要给类型就可以
4.mallco申请空间失败时返回NULL,因此在使用时需要进行判空操作 ,new不需要,new需要捕获异常
5.malloc返回值是void*,使用时需要进行强转,new不需要,只需要给空间的类型即可 

6.申请自定义类型对象时,mallco/free只会开辟空间和释放空间,不会调用构造函数与析构函数,而new在申请空间后调用构造函数完成对象初始化,delete释放空间前会调用析构函数完成资源清理

7.new/delete比malloc/free效率稍微低些,因此new/delete底层封装了malloc/free

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值