C++内存管理

本文详细对比了C语言中的malloc,calloc,realloc与C++的new,delete在内存管理上的差异,包括初始化、扩容、自定义类型的支持以及内存泄漏的概念。特别强调了new和delete在创建和销毁对象时会调用构造函数和析构函数的特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C语言中我们学习了malloc,calloc,realloc,free关于内存管理的函数,C++中引入了new和delete的概念,接下来详细聊聊他们的区别,以及new和delete的用法及与C中内存管理函数进行比较。

首先我们来回顾malloc,calloc,realloc的知识点,三者都是用来开辟内存空间的

malloc/calloc/realloc

malloc(size_t size),malloc只包含一个参数,就是要开辟的空间的大小。

calloc(size_t num, size_t size),calloc有两个参数,第一个参数是有多少个元素,第二个参数就是表明一个元素的内存大小。 这里值得一提的是:使用**calloc会自动将元素初始化为0**。这也是与malloc很不同的一个点。

realloc(void* ptr, size_t size),realloc则是对已有的空间进行扩容,如果已有空间周围的空间不足,则会另找一块新空间,将原来的数据移植过来。 第一个参数是要进行扩容空间的地址,第二个参数是扩容后的总大小。(这里要特别注意是总大小,不是新开的大小

new/delete

new用来开辟空间,形式为 new 新开辟空间的类型,这样可以开辟一个空间出来
如果要开辟多个空间就采用 new 新开辟空间的类型[这里面放入要开辟空间的大小
new也可以传递参数来进行初始化

delete用来销毁开辟的空间 ,形式为delete 指针
如果是销毁多个空间,则形式为delete[] 指针,这个大括号是必须得有的,如果少了就会报错,括号里面不需要写入开辟空间的大小

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

这里我们还得注意ptr5和ptr6,虽然都是写入的10。但第一个10表示的是将一个空间初始值为10,而第二个表示的是开辟10个空间,没有初始化的概念!
在这里插入图片描述
好,到目前也还没有看出new,delete的优势在哪儿,接着说说他们的优势

new和delete操作自定义类型

// new/delete 和 malloc/free最大区别是 new/delete对于【自定义类型】除了开空间,还会调用构造函数和析构函数

class A
{
public:
A(int a = 0)
: _a(a)
{
cout << "A():" << this << endl;
}
~A()
{
cout << "~A():" << this << endl;
}
private:
int _a;
};
int main()
{
//调用构造函数和析构函数
A* p1 = (A*)malloc(sizeof(A));
A* p2 = new A(1);
free(p1);
delete p2;

A* p3 = (A*)malloc(sizeof(A)*10);
A* p4 = new A[10];
free(p3);
delete[] p4;
return 0;
}

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

operator new 和 operator delete

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

operator new 实际也是通过malloc来申请空间,operator delete 最终是通过free来释放空间的。值得一提的是,operator new调用时如果malloc申请空间成功就直接返回,否则执行用户提供的空间不足应对措施,如果用户提供该措施就继续申请,否则就抛异常

new和delete的实现原理

1.内置类型:
如果申请的是内置类型的空间,new和malloc,delete和free基本类似,不同的地方是:
new/delete申请和释放的是单个元素的空间,new[]和delete[]申请的是连续空间而且new在申请空间失败时会抛异常,malloc会返回NULL

2.自定义类型
new的原理
① 调用operator new函数申请空间
② 在申请的空间上执行构造函数,完成对象的构造
delete的原理
① 在空间上执行析构函数,完成对象中资源的清理工作
② 调用operator delete函数释放对象的空间
new T[N]的原理
① 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对
象空间的申请
② 在申请的空间上执行N次构造函数
delete[]的原理
① 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理
② 调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释
放空间

这里要提的是,一定注意delete,一定是执行析构函数才去释放对象的空间,否则可能出现内存泄漏的问题。
在这里插入图片描述

malloc/free和new/delete的区别

malloc/free和new/delete的共同点是:都是从堆上申请空间,并且需要用户手动释放。不同的地方是:
① malloc和free是函数,new和delete是操作符
② malloc申请的空间不会初始化,new可以初始化
③ malloc申请空间时,需要手动计算空间大小并传递,new只需在其后跟上空间的类型即可,如果是多个对象,[]中指定对象个数即可
④ malloc的返回值为void*, 在使用时必须强转,new不需要,因为new后跟的是空间的类型
⑤ malloc申请空间失败时,返回的是NULL,因此使用时必须判空,new不需要,但是new需要捕获异常
⑥ 申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理

内存泄漏概念

内存泄漏是指:由于操作失误或疏忽导致已无法使用的内存没有得到释放。内存泄漏不是内存在物理上的消失,它指的是失去了对那段空间的控制,造成空间的浪费。(上面提及的delete实现原理顺序就与这有关)

内存泄漏的危害:长期运行的程序出现内存泄漏,影响很大,如操作系统、后台服务等等,出现内存泄漏会导致响应越来越慢,最终卡死。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值