C++标准模板(STL)- 低层内存管理 - 分配函数(operator new, operator new[])

低层内存管理

new 表达式是创建拥有动态存储期对象或对象数组的仅有方式,即它们拥有不受制于创建所它们在的作用域的生存期。 new 表达式通过调用分配函数获得存储。 delete 表达式销毁最终导出对象或通过 new 表达式创造的数组,然后调用解分配函数。默认分配函数和默认解分配函数,及与之关联的函数、类型及对象声明于头文件 <new> 。

分配函数

|---------------------------------------------------------------------------------------------|------|-----------|
| 定义于头文件 <new> | | |
| 可替换分配函数 \[nodiscard] (C++20 起) | | |
| void* operator new ( std::size_t count ); | (1) | |
| void* operator new\[\]( std::size_t count ); | (2) | |
| void* operator new ( std::size_t count, std::align_val_t al); | (3) | (C++17 起) |
| void* operator new\[\]( std::size_t count, std::align_val_t al); | (4) | (C++17 起) |
| | | |
| 可替换不抛出分配函数 \[nodiscard] (C++20 起) | | |
| void* operator new ( std::size_t count, const std::nothrow_t& tag); | (5) | |
| void* operator new\[\]( std::size_t count, const std::nothrow_t& tag); | (6) | |
| void* operator new ( std::size_t count, std::align_val_t al, const std::nothrow_t&); | (7) | (C++17 起) |
| void* operator new\[\]( std::size_t count, std::align_val_t al, const std::nothrow_t&); | (8) | (C++17 起) |
| | | |
| 不分配布置分配函数 \[nodiscard] (C++20 起) | | |
| void* operator new ( std::size_t count, void* ptr ); | (9) | |
| void* operator new\[\]( std::size_t count, void* ptr ); | (10) | |
| | | |
| 用户定义布置分配函数 | | |
| void* operator new ( std::size_t count, user-defined-args... ); | (11) | |
| void* operator new\[\]( std::size_t count, user-defined-args... ); | (12) | |
| void* operator new ( std::size_t count, std::align_val_t al, user-defined-args... ); | (13) | (C++17 起) |
| void* operator new\[\]( std::size_t count, std::align_val_t al, user-defined-args... ); | (14) | (C++17 起) |
| | | |
| 类特定分配函数 | | |
| void* T::operator new ( std::size_t count ); | (15) | |
| void* T::operator new\[\]( std::size_t count ); | (16) | |
| void* T::operator new ( std::size_t count, std::align_val_t al ); | (17) | (C++17 起) |
| void* T::operator new\[\]( std::size_t count, std::align_val_t al ); | (18) | (C++17 起) |
| | | |
| 类特定布置分配函数 | | |
| void* T::operator new ( std::size_t count, user-defined-args... ); | (19) | |
| void* T::operator new\[\]( std::size_t count, user-defined-args... ); | (20) | |
| void* T::operator new ( std::size_t count, std::align_val_t al, user-defined-args... ); | (21) | (C++17 起) |
| void* T::operator new\[\]( std::size_t count, std::align_val_t al, user-defined-args... ); | (22) | (C++17 起) |

分配请求数量的字节。这些分配函数为 new 表达式所调用,以分配将被初始化的对象所在的内存。亦可用常规函数调用语法调用它们。

  1. 为非数组 new 表达式所调用,以分配为单个对象请求的存储。标准库实现从自由存储分配 count 字节。失败情况下,标准库实现调用 std::get_new_handler 所返回的函数指针,并重复尝试分配,直到 new 处理函数不返回或成为空指针,在该时刻抛出 std::bad_alloc 。要求此函数返回指向拥有请求大小的对象的适当对齐的指针。

  2. 为 new\[\] 表达式的数组形式所调用,以分配为数组请求的所有存储(包含可能的 new 表达式开销)。标准库实现调用版本 (1)

  3. 为非数组 new 表达式调用,以分配对齐要求超出 __STDCPP_DEFAULT_NEW_ALIGNMENT__ 的单个对象所要求的存储

  4. 为 new\[\] 表达式的数组形式调用,以分配对齐要求超出 __STDCPP_DEFAULT_NEW_ALIGNMENT__ 的对象数组要求的所有存储

  5. 为不抛出非数组 new 表达式所调用。标准库实现调用版本 (1) 并在失败时不传播异常而抛出空指针。

  6. 为 new\[\] 表达式的不抛出数组形式所调用。标准库实现调用版本 (2) 并在失败时不传播异常而抛出空指针。

  7. 在对象对齐要求超出 __STDCPP_DEFAULT_NEW_ALIGNMENT__ 时为不抛出非数组 new 表达式所调用。标准库实现调用版本 (3) 并在失败时不传播异常而抛出空指针。

  8. 在数组元素的对齐要求超出 __STDCPP_DEFAULT_NEW_ALIGNMENT__ 时为 new\[\] 表达式的不抛出数组形式所调用。标准库实现调用版本 (4) 并在失败时不传播异常而抛出空指针。

  9. 为标准单对象布置 new 表达式所调用,标准库实现不进行任何动作并返回不修改的 ptr 。

  10. 为标准数组形式布置 new 表达式所调用。标准库实现不进行任何动作并返回不修改的 ptr 。

  11. 若定义,则为拥有匹配签名的自定义单对象布置 new 表达式所调用。若定义类特定版本 (19) ,则优先于 (11) 调用类特定版本。若用户既不提供 (11) 又不提供 (19) ,则布置 new 表达式为病式。

  12. 若定义,则为拥有匹配签名的自定义数组形式布置 new 表达式所调用。若定义类特定版本 (20) ,则优先于 (12) 调用类特定版本。若用户既不提供 (12) 又不提供 (20) ,则布置 new 表达式为病式。

  13. 若定义,则为拥有匹配签名的自定义单对象布置 new 表达式所调用,若对象的对齐要求超出 __STDCPP_DEFAULT_NEW_ALIGNMENT__ 。若定义类特定版本( (15) 或 (17) ),则调用之。若既不提供类特定版本又不提供具对齐布置形式(此形式),则替而查找无对齐布置形式 (11) 。

  14. 若定义,则为拥有匹配签名的自定义数组形式布置 new 表达式所调用,若元素的对齐要求超出 __STDCPP_DEFAULT_NEW_ALIGNMENT__ 。若定义类特定版本((16) 或 (18) ),则调用之。若既不提供类特定版本又不提供具对齐布置形式(此形式),则替而查找无对齐布置形式 (12) 。

  15. 若定义,则为通常的单对象 new 表达式所调用,若在分配 T 类型对象。

  16. 若定义,则为通常的数组 new\[\] 表达式所调用,若在分配 T 类型对象的数组。

  17. 若定义,则为通常的单对象 new 表达式所调用,若在分配 T 类型对象,且其对齐要求超出 __STDCPP_DEFAULT_NEW_ALIGNMENT__ 。若不提供此重载,但提供了无对齐成员形式 (15) ,则调用无对齐成员重载。

  18. 若定义,通常的数组 new\[\] 表达式所调用,若在分配 T 类型的对象数组,且其对齐要求超出 __STDCPP_DEFAULT_NEW_ALIGNMENT__ 。若不提供此重载,但提供了无对齐成员形式 (16) ,则调用无对齐成员重载。

  19. 若定义,则为拥有匹配签名的自定义单对象布置 new 表达式所调用,若在分配 T 类型对象。

  20. 若定义,则为拥有匹配签名的自定义数组形式布置 new 表达式所调用,若在分配 T 类型对象的数组。

  21. 若定义,则为拥有匹配签名的自定义单对象布置 new 表达式所调用,若在分配 T 类型对象,且其对齐要求超出 __STDCPP_DEFAULT_NEW_ALIGNMENT__ 。若不提供此重载,但提供了无对齐成员形式 (19) ,则调用无对齐成员重载。

  22. 若定义,则为拥有匹配签名的自定义数组形式布置 new 表达式所调用,若在分配 T 类型的对象数组,且其对齐要求超出 __STDCPP_DEFAULT_NEW_ALIGNMENT__ 。若不提供此重载,但提供了无对齐成员形式 (20) ,则调用无对齐成员重载。

参数

|-------|---|-----------------------|
| count | - | 要分配的字节数 |
| ptr | - | 指向要初始化的对象所在的内存区域的指针 |
| tag | - | 用于选择不抛出重载的消歧义标签 |
| al | - | 使用的对齐。若此非有效对齐值,则行为未定义 |

返回值

1-4) 非空指针,指向拥有至少 size 大小的适当对齐的内存

5-8) 非空指针,指向拥有至少 size 大小的适当对齐的内存,或在失败时为空指针

9-10) ptr

11-22) 若函数在分配失败时不返回则同 (1-4) ,否则同 (5-8)

异常

1-4) 在分配内存失败时抛出 std::bad_alloc 或任何从 std::bad_alloc 派生的异常 (C++11 起)

5-10)

|-----------------------|-----------|
| (无) | (C++11 前) |
| noexcept 规定: noexcept | (C++11 起) |

11-22) 若函数在分配失败时不返回则同 (1-4) ,否则同 (5-8)

全局替换

版本 (1-4) 在每个翻译单元隐式声明,即使不包含 <new> 头文件。版本 (1-8) 是可替换的:定义于程序任何位置,在任何源文件的用户提供的拥有相同签名的非成员函数,会替换默认版本。其声明不必可见。

若程序中为任何可替换分配函数提供多于一个替换版本,或若替换定义带 inline 指定符,则行为未定义。若替换定义于异于全局命名空间的命名空间中,或它定义为在全局作用域的 static 函数,则程序为病式。

|-----------------------------------------------------------------------------------------------------------|-----------|
| nothrow 版本的标准库实现 (5-8) 直接调用对应的抛出版本 (1-4) 。抛出的数组版本的标准库实现 (2,4) 直接调用对应的单对象版本 (1,3) 。故而,替换抛出单对象分配函数足以处理所有分配。 | (C++11 起) |

相关推荐
初心未改HD6 小时前
DSH Skill开发实战:SKILL.md是给LLM看的操作手册,不是给人看的README,踩了4个坑
java·大数据·开发语言
Wang's Blog7 小时前
Java 项目实战: 交友项目 - SpringData-Mongo 环境搭建和 CRUD
java·开发语言·交友
凯瑟琳.奥古斯特7 小时前
动态调优IoU提升OCR文本合并精度
开发语言·python·算法
陌陌龙7 小时前
【紧急预警!PHP 核弹级漏洞 php2shell】
开发语言·php
白露与泡影7 小时前
一线 Java 后端面试八股(2026 更新版,含完整答案)
java·开发语言·面试
企业解惑小能手-域智盾系统7 小时前
内网监控软件策略不生效、日志缺失?一套从现象到根因的排查框架
开发语言·php·域智盾
1024奇点7 小时前
【仓颉语言入门 · 第二篇 第 10 课】
开发语言·数据库·ide·mysql·开源
布莱克6057 小时前
A* 算法详解:从原理到实现
开发语言·c++·算法
多弗朗皮卡丘7 小时前
C++ 智能指针
开发语言·c++·c++11·智能指针
数据狐(Datafox)7 小时前
一文读懂京东商品详情API:返回字段解读与 JSON 样例
java·开发语言·数据库·windows·json