C++标准模板(STL)- 低层内存管理 - 分配函数(operator new, operator new[])
创始人
2024-11-13 10:10:37
0次

低层内存管理

new 表达式是创建拥有动态存储期对象或对象数组的仅有方式,即它们拥有不受制于创建所它们在的作用域的生存期。 new 表达式通过调用分配函数获得存储。 delete 表达式销毁最终导出对象或通过 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) 在每个翻译单元隐式声明,即使不包含 头文件。版本 (1-8) 是可替换的:定义于程序任何位置,在任何源文件的用户提供的拥有相同签名的非成员函数,会替换默认版本。其声明不必可见。

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

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

(C++11 起)

相关内容

热门资讯

实测交流透视挂!宝玛大厅ai智... 实测交流透视挂!宝玛大厅ai智能透视挂教程,宝玛大厅破解软件经验(本来有挂辅助)1、每一步都需要思考...
总算了解辅助器!朱雀吴江三缺一... 总算了解辅助器!朱雀吴江三缺一ai智能透视辅助挂技巧,朱雀吴江三缺一好像是有挂(有辅助挂细节)朱雀吴...
今日公布透视!九五至尊大厅ai... 今日公布透视!九五至尊大厅ai智能透视插件,九五至尊大厅有没有透视挂窍门(切实有挂技术)1、在九五至...
玩家必看科普开挂!聚闲麻将ai... 玩家必看科普开挂!聚闲麻将ai智能透视辅助挂软件,聚闲麻将总是真的有挂(有辅助挂方式)聚闲麻将能透视...
据报道开挂!旅游娱乐ai智能开... 据报道开挂!旅游娱乐ai智能开挂工具,旅游娱乐辅助工具演示(一直有挂教学)1、全新机制【旅游娱乐ai...
一分钟揭秘开挂!决胜朋来麻将a... 一分钟揭秘开挂!决胜朋来麻将ai智能透视辅助挂教程,决胜朋来麻将真是真的是有挂(有辅助挂总结)1、首...
如何分辨真伪透视!红牛ai智能... 如何分辨真伪透视!红牛ai智能透视攻略,红牛是不是有挂经验(真是有挂技术)1、操作简单,无需红牛手机...
2分钟细说辅助器!江湖大庆麻将... 2分钟细说辅助器!江湖大庆麻将ai智能透视辅助挂攻略,江湖大庆麻将竟然是真的有挂(有辅助挂头条)1、...
总算清楚透视挂!老夫子厅ai智... 总算清楚透视挂!老夫子厅ai智能透视挂技巧,老夫子厅怎么开挂课程(好像发现有挂)老夫子厅破解侠是真的...
解密关于辅助!菜鸟麻将ai智能... 解密关于辅助!菜鸟麻将ai智能透视辅助挂脚本,菜鸟麻将总是存在有挂(有辅助挂存在)1、用户打开应用后...