C/C++ 内存管理(2)

Hello!!大家早上中午晚上好!!!今天继续复习内存管理部分知识点!!!

一、new/delete和malloc/free的区别

1.1对于申请单个空间内置类型没啥区别
int main()
{
	int* p1 = (int*)malloc(sizeof(int));
	int* p2 = new int;
	int* p3 = new int(1);
	free(p1);
	delete p2;
	delete p3;
	return 0;
}
1.2对于申请多个空间内置类型没啥区别
int main()
{
	int* p1 = (int*)malloc(sizeof(int) * 5);
	int* p2 = new int[5];
	int* p3 = new int[5] {1, 2, 3, 4, 5};
	free(p1);
	delete[]p2;
	delete[]p3;
	return 0;
}

对于内置类型要真说有点区别就是,new的时候无论单个空间还是多个空间都可以任意初始化,而malloc不行

1.3对于申请单个空间的自定义类型
class A
{
public:
	A()
	{
		cout << "A()" << endl;
	}
	~A()
	{
		cout << "~A()" << endl;
	}
private:
	int _a;
};
int main()
{
	A* p1 = (A*)malloc(sizeof(A));
	A* p2 = new A;
	free(p1);
	delete p2;
	return 0;
}

 运行:

对于申请单个空间,new自定义类型会在new的时候调用构造函数创建对象,在delete的时候调用析构函数清理对象资源;malloc和free跟申请释放内置类型没区别; 

1.4对于申请多个空间的自定义类型
int main()
{
	A* p1 = (A*)malloc(sizeof(A) * 10);
	A* p2 = new A[10];
	free(p1);
	delete[]p2;
	return 0;
}

mallco跟malloc内置类型区别:

new多少个A就调用多少次A的构造:

free跟free内置类型没区别:

delete时,创建了几个对象就调用几次析构:

1.5小结

①malloc/free的使用对于内置类型和自定义类型都一样;

②new/delete的使用对于内置类型跟malloc/free没区别,对于自定义类型new n个对象就调用n次构造,delete时创建n对象就调用n次析构;

③new的时候可以初始化任意值,而malloc不能初始化(就算是calloc也只能初始化为0);

④注意new和delete申请释放单个空间、new[]和delete[]申请释放连续空间,配套使用!!!

二、operator new和operator delete

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

2.1operator new

operator new当申请空间成功时,直接返回这块空间的地址;

operator new当申请空间失败时会先执行应对空间不足的措施,如果用户设置了该措施,则继续申请,否则抛异常;

void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
 {
 // try to allocate size bytes
 void *p;
 while ((p = malloc(size)) == 0)
 if (_callnewh(size) == 0)
 {
 // report no memory
 // 如果申请内存失败了,这里会抛出bad_alloc 类型异常
static const std::bad_alloc nomem;
 _RAISE(nomem);
 }
 return (p);
 }
2.2operator delete

operator delete该函数最终是通过free来释放空间;

三、new和delete实现原理

3.1对于内置类型

new/delete和malloc/free基本类似;

3.2对于自定义类型

假设自定义类型为一个简单的Stack:

struct Stack
{
public:
	Stack()
	{
		_array = (int*)malloc(sizeof(int) * 20);
		if (_array == NULL)
		{
			perror("Stack()");
		}
        _capacity=20;
        _size=0;
	}
	~Stack()
	{
		if(_array)
		free(_array);
		_array = NULL;
	}
private:
	int* _array;
	int _capacity;
	int _size;
};

new实现原理:

①先调用operator new开空间;

②再在开好的空间上调用构造函数创建对象;

new[]实现原理:

①先调用operator new[]函数,operator new[]实际上是调用operator new函数申请n个对象空间;

②再在开好的n个对象的空间上调用n次构造函数对n个对象进行初始化工作;

delete实现原理:

①在空间上执行析构函数,完成对象资源的清理工作;

②调用operator delete函数释放对象空间;

delete[]实现原理:

①在n个对象空间上执行n次析构函数,完成对n个对象资源的清理工作;

②调用operator delete[]函数,operator delete[]函数实际上是调用operator delete释放n个对象空间; 

四、总结new/malloc 和delete/free 区别

唯一共同点是new和malloc都时在堆上申请开辟空间,且都需要手动释放;

不同点:

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

2.malloc需要手动传入开辟空间字节数大小,new只需要在后面跟上对象类型就行,如果new多个对象只需要new []里面添加个数即可;

3.malloc如果申请失败返回空值,所以使用前必须判空,new不需要但new需要捕获异常;

4.malloc出来后的空间地址需要强转,new不需要,因为new后面跟的是对象类型;

5.malloc空间不会初始化,new可以初始化;

6.malloc、free空间不会调用构造、析构函数;new会先开空间再调用构造函数,delete会先调用析构函数再释放空间;

五、内存泄漏

5.1什么是内存泄漏?

内存泄漏指的是因程序的错误设计,造成程序未能释放已经不使用的内存。内存泄漏并不是指内存在物理上的消失,而是因错误设计导致丧失对某内存段的控制,从而造成内存浪费!

5.2内存泄漏的危害?

长期运行的程序造成内存泄漏后果很严重,例如操作系统、后台服务等,出现内存泄漏会导致响应越来越慢,最终卡死

六、如何避免内存泄漏?

1、良好的程序设计规范,良好的代码编写规范,只要有动态内存申请的地方就记得配套内存释放;

2、有时候碰上异常,记得释放了也无济于事,这时就得使用智能指针解决;

3、使用内存泄漏检测工具;

几款内存检测工具:

4、简而言之,事前预防使用智能指针,事后补救使用内存泄漏检测工具!

今天就复习到这里!如果您觉得有收获请点赞收藏+关注!谢谢!!

如果您有更好的意见欢迎评论区留言!!

咱们下期见!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值