- 为什么要重载
new操作符- 定制内存管理:默认的
new操作符按照标准方式分配内存,在某些情况下,比如需要特定的内存对齐、使用特殊的内存池,或者对内存分配进行统计等,就需要重载new操作符来自定义内存分配行为。 - 提高性能:对于频繁分配和释放内存的场景,使用定制的内存分配策略可以减少内存碎片,提高内存分配和释放的效率。
- 定制内存管理:默认的
- 重载全局
new操作符- 语法:
cpp
void* operator new(std::size_t size) { // 自定义内存分配逻辑 void* ptr = std::malloc(size); if (!ptr) { throw std::bad_alloc(); } return ptr; }- 说明:
- 全局
new操作符的重载函数必须返回一个指向分配内存的指针,如果分配失败,应抛出std::bad_alloc异常。 std::size_t是new操作符传入的参数,表示需要分配的内存大小(以字节为单位)。- 在上述示例中,我们使用
std::malloc进行内存分配,这是一种简单的替代默认new操作符行为的方式。实际应用中,可以实现更复杂的内存管理策略,如内存池技术。
- 全局
- 重载类专属的
new操作符- 语法:
cpp
class MyClass { public: void* operator new(std::size_t size) { // 类专属的内存分配逻辑 void* ptr = std::malloc(size); if (!ptr) { throw std::bad_alloc(); } return ptr; } };- 说明:
- 类专属的
new操作符仅对该类的对象分配内存时起作用。当使用new MyClass()创建对象时,会调用这个重载的new操作符。 - 同样,如果分配失败,应抛出
std::bad_alloc异常。
- 类专属的
- 重载
new操作符并进行内存对齐- 语法:
cpp
void* operator new(std::size_t size, std::align_val_t alignment) { void* ptr = nullptr; int err = std::posix_memalign(&ptr, static_cast<size_t>(alignment), size); if (err) { throw std::bad_alloc(); } return ptr; }- 说明:
- 这种形式的
new操作符重载用于实现特定的内存对齐。std::align_val_t表示对齐值,常见的对齐值如alignas(16)表示按 16 字节对齐。 std::posix_memalign是 POSIX 标准库中的函数,用于分配对齐的内存。如果分配成功,ptr将指向对齐后的内存地址;如果失败,err将为非零值,此时应抛出std::bad_alloc异常。
- 这种形式的
- 重载
delete操作符- 全局
delete操作符重载:
- 全局
cpp
void operator delete(void* ptr) noexcept { std::free(ptr); }- 类专属
delete操作符重载:
cpp
class MyClass { public: void* operator new(std::size_t size) { void* ptr = std::malloc(size); if (!ptr) { throw std::bad_alloc(); } return ptr; } void operator delete(void* ptr) noexcept { std::free(ptr); } };- 说明:
delete操作符的重载必须与对应的new操作符重载相匹配。当使用delete释放通过重载new操作符分配的内存时,会调用对应的重载delete操作符。- 全局
delete操作符用于释放全局new操作符分配的内存,类专属delete操作符用于释放该类对象通过类专属new操作符分配的内存。 noexcept说明该函数不会抛出异常,这是delete操作符重载的要求。
重载new操作符时,要谨慎处理内存分配和异常情况,确保内存管理的正确性和安全性。同时,合理使用delete操作符的重载来匹配new操作符,避免内存泄漏。