51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

C++ operator new/delete 函数重载

在 C++ 中,operator newoperator delete 是用于动态内存分配和释放的运算符。重载这两个运算符可以使你在分配或释放内存时添加额外的行为,例如跟踪内存使用情况或实现自定义的内存池。

operator newoperator delete 支持全局重载以及类内重载。全局重载允许在整个程序中统一管理内存分配和释放行为,而类内重载则提供了针对特定类的自定义内存管理方式,允许开发者为该类的对象分配和释放内存时实施特定的策略。operator new[]operator delete[] 也是类似地支持全局和类内重载,用于处理动态数组的内存管理。

  1. 全局重载 {#title-0} ==================

可以在任何地方定义重载的 operator newoperator delete,使得所有对象的内存分配和释放行为遵循自定义逻辑。

  1. 演示 {#title-1}

  1. 如何重载标准的内存分配/释放函数?
  2. 如何重载带有额外参数的内存分配和释放函数?
#if 1
#include <iostream>
using namespace std;

struct Demo { Demo() { cout << "Demo 构造函数" << endl; } ~Demo() { cout << "Demo 析构函数" << endl; } };

// 1. 如何重载标准的内存分配/释放函数? void* operator new(size_t size) { cout << "对象内存分配函数" << endl; return malloc(size);; }

void operator delete(void* ptr) { cout << "对象内存释放函数" << endl; free(ptr); }

void* operator new[](size_t size) { cout << "数组内存分配函数" << endl; return malloc(size);; }

void operator delete[](void* ptr) { cout << "数组内存释放函数" << endl; free(ptr); }

void test01() { Demo* d1 = new Demo; delete d1;

int* d2 = new int;
delete d2;

Demo* d3 = new Demo[2]; delete[] d3;

}

// 2. 如何重载带有额外参数的内存分配和释放函数? /* 带额外参数的 operator new/delete 允许对象分配内存时,传入额外的信息

需要注意的是:

  1. 每个重载的 operator new 都应该有对应的 operator delete,即:成对出现
  2. 任意版本的 operator new 分配的内存: 2.1 正常情况下,手动由标准的 delete 运算符调用标准的 operator delete 函数释放 2.2 异常情况下,自动由 oeprator new 对应的 operator delete 函数释放 */

struct Sample { Sample() { cout << "Sample 构造函数" << endl; throw exception(); }

~Sample()
{
	cout &lt;&lt; &quot;Sample 析构函数&quot; &lt;&lt; endl;
}

};

void* operator new(size_t size, const char* file, int line) { cout << "非标准的对象内存分配函数,文件:" << file << " 行号:" << line << endl; return malloc(size); }

void operator delete(void* ptr, const char* file, int line) { cout << "非标准的对象内存释放函数,文件:" << file << " 行号:" << line << endl; free(ptr); }

void* operator new[](size_t size, const char* file, int line) { cout << "非标准的数组内存分配函数,文件:" << file << " 行号:" << line << endl; void* ptr = malloc(size); return ptr; }

void operator delete[](void* ptr, const char* file, int line) { cout << "非标准的数组内存释放函数,文件:" << file << " 行号:" << line << endl; free(ptr); }

void test02() { try { // 单个对象 Sample* s1 = new(FILE, LINE) Sample; delete s1;

	// 对象数组
	Sample* s2 = new Sample[3];
	delete[] s2;
}
catch (const std::exception&amp;)
{
	cout &lt;&lt; &quot;处理异常&quot; &lt;&lt; endl;
}

}

int main() { test01(); test02(); return 0; } #endif

  1. 问题 {#title-2}

在全局重载 operator new/delete 会使得程序出现一些问题:

  1. 全局重载 operator new/delete 会影响程序动态对象的创建和销毁
  2. 全局重载 operator new/delete 会影响到程序依赖库(标准库、第三方库)的使用。
    • 依赖库中在全局重载 operator new/delete,会使得我们的程序使用库中的内存分配行为
    • 在程序中全局重载的 operator new/delete,会使得第三方库的使用我们的内存分配行为
    • 如果程序和依赖库都重载了 operator new/delete 会导致重定义
    • 程序中全局重载 operator delete,可能会导致 STL 容器使用出现问题
#if 1
#include <iostream>
#include <unordered_map>
using namespace std;

struct MemInfo { const char* file; int line; };

unordered_map<void*, MemInfo> records;

void* operator new(size_t size, const char* file, int line) { cout << "内存分配函数" << endl; void* ptr = malloc(size); records[ptr] = { file, line }; return ptr; }

void operator delete(void* ptr) { cout << "内存释放函数" << endl; records.erase(ptr); free(ptr); }

void detect_memory_leak() { if (records.size() > 0) { cout << "检测到内存泄漏" << endl; for (auto& item : records) { cout << item.second.file << " " << item.second.line << endl; } } }

#define new new(FILE, LINE)

void test() { int* p1 = new int; int* p2 = new int; delete p1;

// 检测内存泄漏
detect_memory_leak();

}

int main() { test(); return 0; }

#endif

  1. 类内重载 {#title-3} ==================

在类的定义中可以定义重载的 operator newoperator delete,从而只影响该类的实例。这对于提供特定类的内存管理策略非常有用。

  1. 如何在类内重载标准内存分配和释放函数?
  2. 类内重载带额外参数的内存分配和释放函数?
#if 1
#include <iostream>
using namespace std;

void* operator new(size_t size) { cout << "全局对象内存分配函数" << endl; return malloc(size);; }

void operator delete(void* ptr) { cout << "全局对象内存释放函数" << endl; free(ptr); }

void* operator new[](size_t size) { cout << "全局数组内存分配函数" << endl; return malloc(size);; }

void operator delete[](void* ptr) { cout << "全局数组内存释放函数" << endl; free(ptr); }

// 1. 如何在类内重载标准内存分配和释放函数? /* 1.1 类内重载的内存分配函数必须是静态成员函数 1.2 类内重载的内存分配函数只能影响该类对象的创建 */ struct Demo { Demo() { // throw exception(); }

void* operator new(size_t size)
{
	cout &lt;&lt; &quot;对象内存分配函数&quot; &lt;&lt; endl;
	return malloc(size);;
}

void operator delete(void* ptr) { cout &lt;&lt; &quot;对象内存释放函数&quot; &lt;&lt; endl; free(ptr); }

void* operator new[](size_t size) { cout &lt;&lt; &quot;数组内存分配函数&quot; &lt;&lt; endl; return malloc(size);; }

void operator delete[](void* ptr) { cout &lt;&lt; &quot;数组内存释放函数&quot; &lt;&lt; endl; free(ptr); }

void* operator new(size_t size, const char* file, int line) { cout &lt;&lt; &quot;非标准对象内存分配函数&quot; &lt;&lt; endl; return malloc(size);; }

void operator delete(void* ptr, const char* file, int line) { cout &lt;&lt; &quot;非标准对象内存释放函数&quot; &lt;&lt; endl; free(ptr); }

void* operator new[](size_t size, const char* file, int line) { cout &lt;&lt; &quot;非标准数组内存分配函数&quot; &lt;&lt; endl; return malloc(size);; }

void operator delete[](void* ptr, const char* file, int line) { cout &lt;&lt; &quot;非标准数组内存释放函数&quot; &lt;&lt; endl; free(ptr); }

};

void test01() { // 本类型对象创建使用类内重载的函数 // 调用类内内存分配函数 + 构造函数 // 析构函数 + 调用类内内存释放函数 Demo* d1 = new Demo; delete d1;

Demo* d2 = new Demo[3];
delete[] d2;

// 可以用过全局作用域运算符指定使用全局 // 调用全局内存分配函数 + 构造函数 // 析构函数 + 调用全局内存释放函数 Demo* d3 = ::new Demo; ::delete d3;

Demo* d4 = ::new Demo[3]; ::delete[] d4;

// 其他类型不会受到影响 int* p = new int; delete p;

}

// 2. 类内重载带额外参数的内存分配和释放函数? /*

  1. 每个重载的 operator new 都应该有对应的 operator delete,即:成对出现
  2. 任意版本的 operator new 分配的内存: 2.1 正常情况下,手动由标准的 delete 运算符调用标准的 operator delete 函数释放 2.2 异常情况下,自动由 oeprator new 对应的 operator delete 函数释放 */

void test02() { try { Demo* d1 = new(FILE, LINE) Demo; delete d1;

	Demo* d2 = new(__FILE__, __LINE__) Demo[3];
	delete[] d2;
}
catch (const std::exception&amp;)
{
	cout &lt;&lt; &quot;捕获异常&quot; &lt;&lt; endl;
}

}

int main() { test01(); return 0; } #endif


赞(4)
未经允许不得转载:工具盒子 » C++ operator new/delete 函数重载