有效 C++ 学习备忘录八
2023-12-07 00:48:16
深入探秘 C++ 的内存管理迷宫
踏上 C++ 的探索之旅,你必然会置身于内存管理的迷宫之中。理解 new
和 delete
的奥秘对于驾驭这片复杂之地至关重要。
定制化内存管理:突破默认边界
C++ 提供了高度可定制的内存管理机制,让你超越标准库的既定规则。
set_new_handler
:接管内存分配失败
当内存分配无力回天时,set_new_handler
允许你指定一个函数,在此时此刻挺身而出。这个函数被称为 new-handler 。
void* operator new(size_t size) throw(std::bad_alloc);
new-handler 是一个无类型的函数,接受一个 size_t
参数,表示所需分配的字节数。若能成功分配内存,它应返回指向分配内存块的指针。若失败,它应抛出 std::bad_alloc
异常。
无抛出 new
:异常的绝缘体
在某些场景下,抛出异常是不可承受的,比如实时系统。无抛出 new
(nothrow new) 提供了另一种选择。
void* operator new(size_t size, const std::nothrow_t&) noexcept;
无抛出 new
与标准 new
类似,但它不会抛出 std::bad_alloc
异常。如果内存分配失败,它将返回 nullptr
。
new-handler
行为的内幕
理解 new-handler
的确切行为至关重要。它具有以下特点:
- 默认行为: 未安装 new-handler 时,内存分配失败将导致
std::bad_alloc
异常。 - 安装 new-handler: 安装 new-handler 时,在内存分配失败时将调用它。
- new-handler 返回值: new-handler 可返回
nullptr
来表示分配失败,也可返回指向分配内存的指针。 - 嵌套 new-handler: 当嵌套调用
new
时,嵌套 new-handler 将优先于外部 new-handler。 - 意外异常: 若 new-handler 本身抛出异常,程序将终止。
new-handler
的应用实践
new-handler
可用于多种目的,例如:
- 自定义错误处理: 自定义 new-handler 来处理内存分配失败。
- 内存不足恢复: 在内存不足时采取措施,如释放内存或压缩数据。
- 调试和监视: 监视内存分配模式和调试内存问题。
总结:掌控内存,驾驭迷宫
掌握 new
和 delete
的定制化功能对于有效管理 C++ 中的内存至关重要。通过 set_new_handler
和无抛出 new
,你可以突破默认行为,为特定应用程序定制内存管理机制。
常见问题解答
-
为什么使用
new-handler
而不用try-catch
块?new-handler
允许在程序的全局级别处理内存分配失败,而无需在每个可能发生失败的地方编写try-catch
块。 -
如果 new-handler 抛出异常,会发生什么?
程序将终止,因为 C++ 无法从 new-handler 本身的异常中恢复。
-
无抛出
new
的优势是什么?无抛出
new
可防止在内存分配失败时意外终止程序,这对于实时系统至关重要。 -
如何释放使用
new
分配的内存?使用
delete
运算符释放使用new
分配的内存。 -
如何在多线程环境中使用
new
和delete
?在多线程环境中使用
new
和delete
需要线程安全的内存分配器,如 C++ 标准库中的std::pmr
。