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 起)

相关内容

热门资讯

今天下午!微信老铁13水辅助,... 今天下午!微信老铁13水辅助,潮汕雀友会辅助,总结教程(有挂细节)-哔哩哔哩1、微信老铁13水辅助辅...
详情透视!xpoker辅助!分... 详情透视!xpoker辅助!分辨真假辅助攻略(有挂教程)-哔哩哔哩小薇(辅助器软件下载)致您一封信;...
据监测!欢游互动辅助,蜀山四川... 据监测!欢游互动辅助,蜀山四川破解好友版辅助,手册教程(有挂分析)-哔哩哔哩1、蜀山四川破解好友版辅...
科普透视!wepoker有没有... 科普透视!wepoker有没有插件!每日必看辅助攻略(今日头条)-哔哩哔哩1、操作简单,无需wepo...
据权威媒体报道!雀姬辅助器,四... 据权威媒体报道!雀姬辅助器,四川家园辅助软件,讲义教程(有挂技巧)-哔哩哔哩一、四川家园辅助软件可以...
专业透视!pokemmo辅助官... 专业透视!pokemmo辅助官网!玩家必看教程辅助神器(有挂头条)-哔哩哔哩1、进入到pokemmo...
普及透视!wepoker软件安... 普及透视!wepoker软件安装包!重大通报辅助技巧(真是有挂)-哔哩哔哩暗藏猫腻,小编详细说明we...
有消息称!衢州都莱有没有辅助器... 有消息称!衢州都莱有没有辅助器,钱塘十水三挂件,攻略教程(有挂教学)-哔哩哔哩衢州都莱有没有辅助器破...
关于透视!hhpoker德州牛... 关于透视!hhpoker德州牛仔视频!总算清楚辅助技巧(有挂解惑)-哔哩哔哩1、点击下载安装,hhp...
针对!天天微友辅助器通用版,广... 针对!天天微友辅助器通用版,广东雀神智能辅助照片,学习教程(有挂教学)-哔哩哔哩1、下载好天天微友辅...