详解c++动态内存管理,带你理清new和delete操作符的用法

目录

前言 

一、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++中可以继续使用,但有些地方就无能为力而且使用起来比较麻烦,因此C++又提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理。其中new可以替代malloc的功能,delete可以替代free的功能。

1.基本语法

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类型空间),且对象是自定义类型时,释放时在指针前面必须加一个[ ],否则会发生内存泄漏(这里的内存泄露指的是自定义类型的析构函数只会调用一次),编译时没有问题,但是运行时会发生崩溃。如果对象是内置类型的话可以不加[ ],但不建议这样使用。

2.new和delete操作自定义类型

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在申请自定义类型空间时,也可以传值进行初始化。

二、 operator new与operator delete函数

1.基本概念

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

我们通过参考系统源码可以得知,operator new实际也是通过malloc来申请空间,operator实际也是通过free来释放空间的。 

2.new和delete的实现原理

new的基本原理:

(1)调用operator new函数申请空间

(2)在申请的空间上执行构造函数

delete的基本原理:

(1)在空间上执行析构函数

(2)调用operator 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.申请自定义类型空间时,new会调用它的构造函数,delete会调用它的析构函数,而malloc/free不会。

四、如何一次性在堆上申请4G的空间

最后,给大家出一个小问题,我们最多一次性可以在堆上申请多少空间呢?

经过我的测试,在32位的编译器下,malloc/new最大能申请2g左右的空间。如果需要一次性申请更多的空间,我们则需要将编译器调成64位。

大家不妨用下面的代码做个测试:

// 将程序编译成x64的进程,运行下面的程序试试?
#include <iostream>
using namespace std;
int main()
{
	void* p = new char[0xfffffffful];
	cout << "new:" << p << endl;
	return 0;
}

总结

以上就是今天要讲的内容,本文主要讲解了c++中新的动态内存管理方式以及new和delete操作符的使用,如果大家觉得有收获的话可以关注博主,我也将努力给大家带来更优质的内容,感谢阅读,您的支持就是我最大的动力。 

猜你喜欢

转载自blog.csdn.net/weixin_59371851/article/details/124617883
今日推荐