目录
前言
一、c++内存管理方式
1.基本语法
2.new和delete操作自定义类型
二、 operator new与operator delete函数
1.基本概念
2.new和delete的实现原理
三、malloc/free和new/delete的区别(重点)
四、如何一次性在堆上申请4G的空间
总结
相信有一定c语言基础的小伙伴都了解动态内存是在堆中开辟的,c语言通过malloc和free等操作符对动态内存进行管理。但是小伙伴们在使用时有没有感到有一些不适呢,例如开辟空间时必须强制类型转换很麻烦,例如在结构体内部开辟的空间总是忘了释放,针对这些问题,c++都做了改进,并增加了新的操作符使我们的操作更加方便快捷,且功能更加完善。话不多说,我们赶紧一起来看看吧。
提示:以下是本篇文章正文内容,下面案例可供参考
C语言内存管理方式在C++中可以继续使用,但有些地方就无能为力而且使用起来比较麻烦,因此C++又提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理。其中new可以替代malloc的功能,delete可以替代free的功能。
c++动态内存的基本语法如下:
void Test()
{
// 动态申请一个int类型大小的空间
int* p1 = new int;
// 动态申请一个int类型的空间并初始化为10
int* p2 = new int(10);
// 动态申请10个int类型的空间
int* p3 = new int[10];
// 动态申请3个int类型的空间并初始化
int* p4 = new int[3]{1,2,3};
//释放空间
delete p1;
delete p2;
delete[] p3;
delete[] p4;
}
可以看出,和c语言相比,c++的语法更加简洁。申请空间时不必再进行指针的强制类型转换,编译器会直接为我们完成,并且增加了初始化功能。
注意:当申请多块空间时(比如p3申请了十个int类型空间),且对象是自定义类型时,释放时在指针前面必须加一个[ ],否则会发生内存泄漏(这里的内存泄露指的是自定义类型的析构函数只会调用一次),编译时没有问题,但是运行时会发生崩溃。如果对象是内置类型的话可以不加[ ],但不建议这样使用。
new与delete对内置类型的操作和malloc与free基本没有区别,但对自定义类型则不同。在申请自定义类型空间时,new会调用自定义类型的构造函数和初始化列表,delete会调用析构函数。而malloc与free不会。
下面我们以链表举例,代码如下:
struct ListNode
{
ListNode* _next;
ListNode* _prev;
int _val;
ListNode(int val = 0)
:_next(nullptr)
, _prev(nullptr)
, _val(val)
{
cout << "ListNode(int val = 0)" << endl;
}
~ListNode()
{
cout << "~ListNode()" << endl;
}
};
int main()
{
// c malloc只是开空间 free释放空间
struct ListNode* n1 = (struct ListNode*)malloc(sizeof(struct ListNode));
free(n1);
// cpp new 针对自定义类型,开空间+构造函数初始化
//delete 针对自定义类型,析构函数清理 + 释放空间
ListNode* n2 = new ListNode(5); // -> 相当于c语言中BuyListNode(5)
delete n2;
}
打印结果如下:
可以看出,构造函数和析构函数都被调用。并且new在申请自定义类型空间时,也可以传值进行初始化。
new和delete是用户进行动态内存申请和释放的操作符。operator new和operator delete是系统提供的全局函数。new在底层调用operator new全局函数来申请空间,delete在底层调用operator delete来释放空间。
我们通过参考系统源码可以得知,operator new实际也是通过malloc来申请空间,operator实际也是通过free来释放空间的。
new的基本原理:
(1)调用operator new函数申请空间
(2)在申请的空间上执行构造函数
delete的基本原理:
(1)在空间上执行析构函数
(2)调用operator delete完成空间的释放
共同点:都是从堆上申请空间,都需要用户手动释放
不同点:
1.malloc和free是函数,new和delete是操作符。
2.malloc申请的空间不会初始化,new会初始化。
3.malloc申请空间时,需要手动进行计算申请的空间大小,new只需在后面跟上空间的类型即可。
4.malloc的返回值是void*,必须进行强转,而new不需要,因为new后面跟的是空间的类型。
5.malloc申请失败时,返回的是NULL,需要判空,new不需要,但new需要捕获异常。
6.申请自定义类型空间时,new会调用它的构造函数,delete会调用它的析构函数,而malloc/free不会。
最后,给大家出一个小问题,我们最多一次性可以在堆上申请多少空间呢?
经过我的测试,在32位的编译器下,malloc/new最大能申请2g左右的空间。如果需要一次性申请更多的空间,我们则需要将编译器调成64位。
大家不妨用下面的代码做个测试:
// 将程序编译成x64的进程,运行下面的程序试试?
#include
using namespace std;
int main()
{
void* p = new char[0xfffffffful];
cout << "new:" << p << endl;
return 0;
}
以上就是今天要讲的内容,本文主要讲解了c++中新的动态内存管理方式以及new和delete操作符的使用,如果大家觉得有收获的话可以关注博主,我也将努力给大家带来更优质的内容,感谢阅读,您的支持就是我最大的动力。