C++动态内存分配,operator new,operator delete以及new定位表达式

C++动态内存分配

operator new/delete函数

new和delete是用户进行动态内存申请和释放的操作符, operator new和operator delete是系统提供的全局函数.

new 在底层调用operator new全局函数申请空间
operator new 函数实际通过malloc申请空间, 当malloc申请空间成功的时候直接返回; 如果申请空间失败, 会尝试执行空间不足的应对措施, 如果该应对措施用户设置了, 就会继续申请, 否则就会抛异常

deldete 在底层通过operator delete全局函数来释放空间
operator delete函数最终是通过free来释放空间的

new和delete实现原理

内置类型

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

自定义类型

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来释放空间

定位new表达式

定位new表达式是在已分配的原始内存空间中调用构造函数初始化一个对象

使用格式
new(address) T或者new(address) T(类型初始化列表)
address必须是一个指针

使用场景
定位new表达式在实际中一般是配合内存池使用, 因为内存池分配出的内存没有初始化, 所以如果是自定义类型的对象, 需要使用new的定义表达式进行显式调用构造函数进行初始化.
代码示例:

#include <iostream>

using namespace std;

class Test
{
	int m_data;
public:
	Test() :
		m_data(0)
	{
		cout << "Test():" << this << endl;
	}

	~Test()
	{
		cout << "~Test():" << this << endl;
	}

};

int main()
{
	//pt指向的是与Test对象相同大小的一块空间, 还不能算是一个对象, 因为构造函数没有执行
	Test * pt = (Test*)malloc(sizeof(Test));

	new(pt) Test;//如果Test的构造函数有参数时, 这里还需要传参

	system("pause");
	return 0;
}

new定位表达式释放是否有必要?
通过new定位表达式申请的空间实际并没有开辟新的空间, 所以不需要通过delete释放, 如果要调用析构函数, 可以使用显式调用的方式
例如: pt->~Test();

发布了235 篇原创文章 · 获赞 28 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_44781107/article/details/103694742