24new和delete的运算符重载视角

new和delete的运算符重载视角

new和malloc对比:

  • malloc按字节开辟内存,返回void*,需要强制类型转换;new开辟内存需要指定类型
  • new在malloc的基础上,还会进行数据的初始化
  • malloc开辟内存失败返回nullptr,new抛出bad_alloc类型的异常

delete和free对比:

  • delete是在free的基础上进行了析构

运算符重载视角

  • 事实上,new是operator new的重载,delete也是operator delete的重载。全局空间下可以重载new和delete。
  • 如何发现程序中的内存泄露?
    • 编写全局作用域的new和delete的运算符重载方法,并自定义一个内存申请与释放的记录表,监视new和delete的记录。
  • new和delete能混用吗?C++为什么可以区分单个元素和数组的内存分配和释放?blog参考
    • 在new对象是,如果对象是单个元素,则直接开辟内存并初始化;如果对象是类对象(且显式定义了析构函数)的数组,则其malloc的空间为4字节+对象数组所需的空间,其中开头4字节用于保存数组长度,不过返回的是数组空间首地址。delete时,delete数组还需free开头四字节的部分。
    • 如果new和delete仅针对简单编译器内置类型做内存开辟和释放,不涉及类对象构造析构,则不会报错
    • 如果new和delete涉及类对象构造析构,且没有配对使用。
      • 将单个对象delete[]:则代码执行会向前探索4字节以获取数组长度,报错。
      • 将数组对delete,则释放第一个元素,不会报错,但存在内存泄漏。
using namespace std;

//先调用operator进行内存开辟,然后自动调用对象的构造函数
void* operator new(size_t size)
{
	void* p = malloc(size);
	if (p == nullptr)
		throw bad_alloc();
	cout << "operator new addr: " << p << endl;
	return p;
}

void* operator new[](size_t size)
{
	void* p = malloc(size);
	if (p == nullptr)
		throw bad_alloc();
	cout << "operator new[] addr: " << p << endl;
	return p;
}

void operator delete(void* ptr)
{
	cout << "operator delete addr: " << ptr << endl;
	free(ptr);
}

void operator delete[](void* ptr)
	{
		cout << "operator delete[] addr: " << ptr << endl;
		free(ptr);
	}

class Test
{
public:
	Test(int data = 10) { cout << "Test()" << endl; }
	~Test() { cout << "~Test()" << endl; }

private:
	int* ptr;
};

int main()
{
	try
	{
		Test* p1 = new Test[6];
		//delete p1;//混用出现问题
		delete []p1;
		int* p = new int[3];
		delete p; //内存泄露,不报错
		int* q = new int(2);
		delete[]q;
	}
	catch (const bad_alloc& err)
	{
		cerr << err.what() << endl;
	}
}
posted @ 2024-01-21 11:28  SIo_2  阅读(15)  评论(0)    收藏  举报