返回

有效 C++ 学习备忘录八

后端

深入探秘 C++ 的内存管理迷宫

踏上 C++ 的探索之旅,你必然会置身于内存管理的迷宫之中。理解 newdelete 的奥秘对于驾驭这片复杂之地至关重要。

定制化内存管理:突破默认边界

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 来处理内存分配失败。
  • 内存不足恢复: 在内存不足时采取措施,如释放内存或压缩数据。
  • 调试和监视: 监视内存分配模式和调试内存问题。

总结:掌控内存,驾驭迷宫

掌握 newdelete 的定制化功能对于有效管理 C++ 中的内存至关重要。通过 set_new_handler 和无抛出 new,你可以突破默认行为,为特定应用程序定制内存管理机制。

常见问题解答

  1. 为什么使用 new-handler 而不用 try-catch 块?

    new-handler 允许在程序的全局级别处理内存分配失败,而无需在每个可能发生失败的地方编写 try-catch 块。

  2. 如果 new-handler 抛出异常,会发生什么?

    程序将终止,因为 C++ 无法从 new-handler 本身的异常中恢复。

  3. 无抛出 new 的优势是什么?

    无抛出 new 可防止在内存分配失败时意外终止程序,这对于实时系统至关重要。

  4. 如何释放使用 new 分配的内存?

    使用 delete 运算符释放使用 new 分配的内存。

  5. 如何在多线程环境中使用 newdelete

    在多线程环境中使用 newdelete 需要线程安全的内存分配器,如 C++ 标准库中的 std::pmr