【C++课程学习】:new和delete为什么要配套使用,new,delete和malloc,free的比较

发布于:2024-07-11 ⋅ 阅读:(47) ⋅ 点赞:(0)

🎁个人主页:我们的五年

🔍系列专栏:C++课程学习

🎉欢迎大家点赞👍评论📝收藏⭐文章

目录

🎡1.new,delete和malloc,free的区别:

⌚️相同点:

⌚️不同点:

🎡2.new和free的实现原理:

1.对内置类型的处理:

2.对自定义类型的处理:

🎡3.为什么尽量要new和delete配套使用,malloc(calloc,realloc)和free配套使用?


🎡1.new,delete和malloc,free的区别:

⌚️相同点:

new,delete和malloc,free都是对动态内存进行管理的。动态内存是位于堆上的,不会随着函数生命周期的结束而结束,正因为这样,所以才要用户主动的进行空间释放。不然就会造成空间泄露。

●空间泄露:不是物理层面的消失,而是我们失去对某块空间的控制。

危害:长期运行的程序出现内存泄漏会使反应越来越慢,最终卡死。

⌚️不同点:

🏆1.new,delete是操作符,malloc,free是函数

🥊操作符和函数的区别:

1.操作符在编译的过程就进行了替代,而函数要在运行中进行调用。

2.操作符不需要要有头文件,由编译器实习,而函数必须要有具体实现。

🏆2.是否能进行初始化:

malloc不可以进行初始化。new可以进行初始化,也可以不进行初始化。


🏆3.是否需要进行类型转化:

malloc申请的空间是void*,所以要进行类型转化,new申请的空间里面有类型,不需要进行转化。


🏆4.空间大小的计算:

malloc要明确申请空间的大小(单位:字节),但是new只要明确申请几个就可以了,申请多个时,在类型后面加[个数]。


🏆5.是否主动调用构造函数和析构函数:

在处理自定义类型的时候,new会调用构造函数,delete会主动调用析构函数对类里面的空间进行清理。但是malloc和free就不会调用。


🏆6.申请失败的返回值不同: 

malloc申请失败的时候返回NULL指针,所以申请完以后,要进行判空。new需要捕获异常

🎡2.new和free的实现原理:

1.对内置类型的处理:

从下面的例子也可以看出来,new可以对申请的空间进行初始化。malloc不能对申请的空间进行初始化,calloc虽然可以初始化,但是都是0,不能根据具体的实际情况进行初始化,所以也是不能初始化。

#include<iostream>
using namespace std;

int main()
{
	//申请一个int空间
	int* p1 = new int(10);

	//malloc申请空间的大小,不进行初始化
	int* p2 = (int*)malloc(sizeof(int));

	//calloc进行初始化,每个字节都初始化为0
	int* p3 = (int*)calloc(1, sizeof(int));

	//对空间进行扩容,如果为空指针,功能相当于malloc
	int* p4 = (int*)realloc(nullptr, sizeof(int));

	//申请多个int空间,后面跟着初始化列表
	int* p5 = new int[5] {1, 2, 3};

	free(p2);
	delete p1;
	//释放多个空间的时候,用delete[] 指针
	delete[] p5;
}

2.对自定义类型的处理:

在自定义这个层面,new和malloc的区别就不止有new可以进行初始化,还有new会主动调用构造函数,delete会调用析构函数。

#include<iostream>
using namespace std;

class A {
public:
	A() {
		cout << "A()" << endl;
	}
	~A() {
		cout << "~A()" << endl;
	}
private:
	int _a;
};
int main()
{
	A* p1 = new A;
	delete p1;
	cout << "aaa" << endl;

	A* p2 = (A*)malloc(sizeof(A));
	free(p2);
	cout << "aaa" << endl;
	
	return 0;
}

3.原理:

⌚️new的原理:

1.operator  new函数申请空间

2.在申请的空间上调用构造函数。

⌚️delete的原理:

1.执行析构函数对对象中的资源进行清理。

2.调用operator delete对对象进行清理


new T[ ]和delete[ ]原理和上面类似。

operator new和operator delete是系统提供的全局函数,底层还是通过malloc和free进行实现的。

🎡3.为什么尽量要new和delete配套使用,malloc(calloc,realloc)和free配套使用?

因为我们如果下面这种情况下,如果是new申请的空间,用free进行释放空间,就会发生错误。

⌚️在类里面我们显式实现了析构函数的时候,用new申请多个类对象的时候,会多申请4个字节(一个int类型的大小)保存申请了多少个类。

#include<iostream>
using namespace std;

class A {
public:
	~A() {
		cout << "~A()" << endl;
	}
private:
	int _a;
};
int main()
{
	A* p1 = new A[10];

	A* p2 = (A*)malloc(sizeof(A) * 10);

	return 0;
}

这时候申请的大小是:4*10+4=44字节

但是如果没有显式实现析构函数,就不要那多出来的四个字节来保存申请了多少个类。

但是new申请的空间返回的是多申请的那四个字节的后面那10个A空间起始位置。

如果我们直接用free释放这一位置,前面多申请的那四个就没有被释放,就发生内存泄漏。