当前位置: 首页 > news >正文

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

低层内存管理


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

解分配函数

operator delete, 
operator delete[]

定义于头文件 <new>

可替换通常解分配函数

void operator delete  ( void* ptr ) throw();

(1)(C++11 前)

void operator delete  ( void* ptr ) noexcept;

(C++11 起)

void operator delete[]( void* ptr ) throw();

(2)(C++11 前)

void operator delete[]( void* ptr ) noexcept;

(C++11 起)

void operator delete  ( void* ptr, std::align_val_t al ) noexcept;

(3)(C++17 起)

void operator delete[]( void* ptr, std::align_val_t al ) noexcept;

(4)(C++17 起)

void operator delete  ( void* ptr, std::size_t sz ) noexcept;

(5)(C++14 起)

void operator delete[]( void* ptr, std::size_t sz ) noexcept;

(6)(C++14 起)

void operator delete  ( void* ptr, std::size_t sz,
                        std::align_val_t al ) noexcept;

(7)(C++17 起)

void operator delete[]( void* ptr, std::size_t sz,
                        std::align_val_t al ) noexcept;

(8)(C++17 起)

可替换布置解分配函数

void operator delete  ( void* ptr, const std::nothrow_t& tag ) throw();

(9)(C++11 前)

void operator delete  ( void* ptr, const std::nothrow_t& tag ) noexcept;

(C++11 起)

void operator delete[]( void* ptr, const std::nothrow_t& tag ) throw();

(10)(C++11 前)

void operator delete[]( void* ptr, const std::nothrow_t& tag ) noexcept;

(C++11 起)

void operator delete  ( void* ptr, std::align_val_t al,
                        const std::nothrow_t& tag ) noexcept;

(11)(C++17 起)

void operator delete[]( void* ptr, std::align_val_t al,
                        const std::nothrow_t& tag ) noexcept;

(12)(C++17 起)

不分配布置解分配函数

void operator delete  ( void* ptr, void* place ) throw();

(13)(C++11 前)

void operator delete  ( void* ptr, void* place ) noexcept;

(C++11 起)

void operator delete[]( void* ptr, void* place ) throw();

(14)(C++11 前)

void operator delete[]( void* ptr, void* place ) noexcept;

(C++11 起)

用户定义的布置解分配函数

void operator delete  ( void* ptr, args... );

(15)

void operator delete[]( void* ptr, args... );

(16)

类特定通常解分配函数

void T::operator delete  ( void* ptr );

(17)

void T::operator delete[]( void* ptr );

(18)

void T::operator delete  ( void* ptr, std::align_val_t al );

(19)(C++17 起)

void T::operator delete[]( void* ptr, std::align_val_t al );

(20)(C++17 起)

void T::operator delete  ( void* ptr, std::size_t sz );

(21)

void T::operator delete[]( void* ptr, std::size_t sz );

(22)

void T::operator delete  ( void* ptr, std::size_t sz, std::align_val_t al );

(23)(C++17 起)

void T::operator delete[]( void* ptr, std::size_t sz, std::align_val_t al );

(24)(C++17 起)

类特定布置解分配函数

void T::operator delete  ( void* ptr, args... );

(25)

void T::operator delete[]( void* ptr, args... );

(26)

类特定销毁解分配函数

void T::operator delete(T* ptr, std::destroying_delete_t);

(27)(C++20 起)

void T::operator delete(T* ptr, std::destroying_delete_t,
                        std::align_val_t al);

(28)(C++20 起)

void T::operator delete(T* ptr, std::destroying_delete_t, std::size_t sz);

(29)(C++20 起)

void T::operator delete(T* ptr, std::destroying_delete_t,
                        std::size_t sz, std::align_val_t al);

(30)(C++20 起)

解分配先前由匹配的 operator new 所分配的存储。这些解分配函数为 delete 表达式与 new 表达式所调用,以在析构(或构造失败)拥有动态存储期的对象后解分配内存。它们亦可用常规函数调用语法调用。

1) 为 delete 表达式所调用,以解分配先前为单对象分配的存储。此函数的标准库实现的行为未定义,除非 ptr 是空指针或是先前从 operator new(size_t) 或 operator new(size_t, std::nothrow_t) 的标准库实现获得的指针。

2) 为 delete[] 表达式所调用,以解分配先前为对象数组分配的存储。此函数的标准库实现的行为未定义,除非 ptr 是空指针或是先前从 operator new[](size_t) 或 operator new[](size_t, std::nothrow_t) 的标准库实现获得的指针。

3,4) 同 (1,2) ,除了若对齐要求超出 __STDCPP_DEFAULT_NEW_ALIGNMENT__ 才被调用

5,6) 若提供用户定义重载,则取代 (1-2) 得到调用,除了在删除不完整类型的对象、非类类型的数组和可平凡析构类类型的数组时,调用 (1-2) 还是 (5-6) 是未指定的。内存分配器可用给定的大小变得更高效。标准库实现等同于 (1-2) 。

7,8) 同 (5-6) ,除了若对齐要求超出 __STDCPP_DEFAULT_NEW_ALIGNMENT__ 才被调用

9) 若对象的构造函数抛出异常,则为不抛出的单对象 new 表达式所调用。标准库实现表现同 (1)

10) 若任何对象的构造函数抛出异常,则(在执行数组中已成功构造的所有对象的析构函数后)为不抛出的数组 new[] 表达式所调用。标准库实现表现同 (2)

11,12) 同 (9,10) ,除了若对齐要求超出 __STDCPP_DEFAULT_NEW_ALIGNMENT__ 才被调用

13) 若对象的构造函数抛出异常,则为标准单对象布置 new 表达式所调用。此函数的标准库实现不做任何事。

14) 若任何对象的构造函数抛出异常,则为布置 new 表达式的数组形式(在执行数组中已成功构造的所有对象的析构函数后)所调用。此函数的标准库实现不做任何事。

15) 若定义,则为拥有匹配签名的自定义单对象布置 new 表达式调用,若对象构造函数抛出异常。若定义类特定版本 (25) ,则类特定版本优先于 (9) 调用。若用户既不提供 (25) 又不提供 (15) ,则不调用解分配函数。

16) 若定义,则为拥有匹配签名的布置 new[] 表达式自定义数组形式(在执行数组中已成功构造的所有对象的析构函数后)调用,若任何对象的构造函数抛出异常。若定义类特定版本 (16) ,则类特定版本优先于 (10) 调用。若用户既不提供 (26) 又不提供 (16) ,则不调用解分配函数。

17) 若定义,则为通常单对象 delete 表达式调用,若在解分配一个 T 类型对象。

18) 若定义,则为通常数组 delete[] 表达式调用,若在解分配 T 类型对象的数组。

19,20) 若定义,则优先于 (17,18) 调用,若对齐要求超出 __STDCPP_DEFAULT_NEW_ALIGNMENT__

21) 若定义,且若未定义 (17) ,则为通常单对象 delete 表达式调用,若在解分配一个 T 类型对象。

22) 若定义,且若未定义 (18) ,则为通常数组 delete[] 表达式调用,若在解分配 T 类型对象的数组。

23,24) 若定义,且若未定义 (19,20) ,则优先于无对齐成员调用,若对齐要求超出 __STDCPP_DEFAULT_NEW_ALIGNMENT__.

25) 若定义,则为拥有匹配签名的自定义单对象布置 new 表达式调用,若对象构造函数抛出异常。若不提供此函数,亦不提供匹配的 (15) ,则不调用解分配函数。

26) 若定义,则为拥有匹配签名的自定义布置 new[] 表达式的数组形式(在执行数组中已成功构造的所有对象的析构函数后)调用,若任何对象的构造函数抛出异常。若不提供此函数,亦不提供匹配的 (16) ,则不调用析构函数。

27-30) 若定义,则 delete 表达式在调用 operator delete 前不对 *p 执行析构函数。取而代之地,变为由此用户定义的 operator delete 负责直接调用析构函数,例如用 p->~T(); 。

通常(非布置)解分配函数的具对齐和不具对齐重载之间的重载决议准确细节见 delete 表达式。

(C++17 起)

所有情况下,若 ptr 是空指针,则标准库解分配函数不做任何事。若传递给标准库解分配函数的指针不是从对应的标准库分配函数取得者,则行为未定义。

在标准库解分配函数返回后,所有引用到被解分配存储的任何部分的指针都变为非法。

已因此方式变为非法的指针的任何使用,即使是复制指针值到另一指针变量,都是未定义行为。

(C++14 前)

通过已因此方式变为非法的指针解引用,以及将它传递给解分配函数(双重 delete )是未定义行为。任何其他使用是实现定义的。

(C++14 起)

参数

ptr-指向要解分配的内存块的指针或空指针
sz-传递给匹配的分配函数的 size
place-用作匹配的布置 new 中布置参数的指针
tag-匹配不抛出 operator new 所用标签的重载消歧义标签
al-被分配的对象或数组元素的对齐
args-匹配布置分配函数的任意参数(可包含 std::size_t 与 std::align_val_t )

返回值

(无)

异常

15-30) 容许用户定义的解分配函数抛异常。

(C++11 前)

15-30) 所有解分配函数均为 noexcept(true) ,除非在声明中另外说明。若解分配函数以抛异常终止,则行为未定义,即使以 noexcept(false) 声明它。

(C++11 起)

全局替换

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

若程序中提供多于一个替换,或若替换声明有 inline 指定符,则行为未定义,若替换声明于异于全局命名空间的命名空间,或若它定义为在全局作用域的 static 非成员函数,则程序为病态。

nothrow 版本 (9,10) 的标准库实现直接调用抛出版本 (1,2) 。具大小解分配函数 (5-8) 的标准库实现直接调用对应的不具大小解分配函数 (1-4) 。不具大小的抛出数组形式 (2,4) 的标准库实现直接调用对应的单对象形式 (1,3) 。

故而,替换抛出的单对象解分配函数 (1,3) 足以处理所有解分配。

(C++11 起)

相关文章:

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

低层内存管理 new 表达式是创建拥有动态存储期对象或对象数组的仅有方式&#xff0c;即它们拥有不受制于创建所它们在的作用域的生存期。 new 表达式通过调用分配函数获得存储。 delete 表达式销毁最终导出对象或通过 new 表达式创造的数组&#xff0c;然后调用解分配函数。默认…...

LeetCode 热题 HOT 100 (025/100)【宇宙最简单版】

【二叉树】No. 0124 二叉树中的最大路径和 【困难】&#x1f449;力扣对应题目指路 希望对你有帮助呀&#xff01;&#xff01;&#x1f49c;&#x1f49c; 如有更好理解的思路&#xff0c;欢迎大家留言补充 ~ 一起加油叭 &#x1f4a6; 欢迎关注、订阅专栏 【力扣详解】谢谢你…...

【mysql 第三篇章】一条 update语句是怎么持久化到磁盘上的?

首先看一下这个 SQL 语句你会不会写? 下面是说明执行这个 SQL 语句&#xff0c;数据库底层做了什么操作。 update users set namexxx where id10;在引擎要执行更新语句的时候&#xff0c;比如更新 id10 这行数据时&#xff0c;他会先查看数据在缓冲池中是否存在&#xff0c;如…...

深入探索大模型:从基础到实践,开启AI之旅

摘要&#xff1a; 在人工智能领域&#xff0c;大模型技术正成为推动创新和进步的关键力量。对于初学者而言&#xff0c;掌握大模型的基本概念、理论和技术是至关重要的。 本文将为你提供一个全面的学习路线&#xff0c;帮助你从基础知识出发&#xff0c;逐步深入到大模型的实践…...

题解:力扣1567 - 返回乘积为正数的最长子数组

问题描述 给定一个整数数组 nums&#xff0c;找出乘积为正数的最长子数组的长度。这里的子数组定义为连续元素的序列&#xff0c;乘积为正数指子数组中正数的个数必须大于负数的个数。 解题思路 为了解决这个问题&#xff0c;我们可以使用两个数组 f 和 g 分别表示以当前位置…...

009 | 上证50ETF基金数据分析及预测

项目背景 中国股市的发展历程坎坷,从最初的茫然到现在的逐步成熟,股市已经成为中国经济发展的重要标志之一。然而,当前中国股市仍存在投机行为过度和定价机制不完善等问题。为更好地理解和预测股市走势,本项目聚焦于上证50ETF基金的历史数据分析和未来走势预测。 项目目标…...

Wakanda: 1靶场复现【附代码】(权限提升)

靶机下载地址&#xff1a; wakanda: 1 ~ VulnHubwakanda: 1, made by xMagass. Download & walkthrough links are available.https://www.vulnhub.com/entry/wakanda-1,251/#download 1. 主机发现端口扫描目录扫描敏感信息获取 1.1. 主机发现 nmap -sn 192.168.7.0/24…...

内核函数调试

要进入 bind 函数的内部进行调试&#xff0c;实际上是不能直接在用户空间代码中进入内核内部的 bind 实现&#xff0c;因为 bind 是一个系统调用&#xff0c;它由内核处理。尽管如此&#xff0c;你可以通过以下几种方法来间接调试 bind 函数并理解它的行为&#xff1a; 1. 使用…...

Spring IOC使用DButil实现对数据库的操作

一、DButil、lombok、junit的简单介绍 1.dbutil dbutil是由阿帕奇提供操作数据库的插件&#xff0c;其核心类为QueryRunner&#xff0c;存在方法 .query() 查询&#xff0c;.update() 增删改&#xff1b; <!-- dbutil --> <dependency><groupId>commons-d…...

Android14音频进阶调试之命令播放mp3/aac非裸流音频(八十)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 新书发布:《Android系统多媒体进阶实战》🚀 优质专栏: Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏: 多媒体系统工程师系列【原创干货持续更…...

vue中怎么自定义组件

目录 一&#xff1a;功能描述 二&#xff1a;实现过程 一&#xff1a;功能描述 在开发过程中我们经常需要自定义组件完成特定的功能&#xff0c;比如用户详情页&#xff0c;我增加一个调整余额的按钮&#xff0c;点击以后需要打开一个调整余额对话框&#xff0c;输入调整的金…...

BM1反转链表[栈+头插法]

题目要求如下: 问题比较简单,就是将链表中的值进行反转即可。 一种比较简单的方式是使用栈链表的方式来实现,下面是相应的代码: #include <stdio.h> #include <stdlib.h> int arr[10001] {0}; struct ListNode* ReverseList(struct ListNode* head ) {if (head …...

VisionPro二次开发学习笔记10-使用 PMAlign和Fixture固定Blob工具检测孔

使用 PMAlign和Fixture固定Blob工具检测孔 这个示例演示了如何使用 PMAlign 工具和 Fixture 工具来夹持一个 Blob 工具。示例代码将检测支架右上角孔的存在。当点击运行按钮时&#xff0c;将读取新图像。PMAlign 工具运行并生成一个 POSE 作为输出。POSE 是一个六自由度的变换…...

学单片机怎么在3-5个月内找到工作?

每个初学者&#xff0c;都如履薄冰&#xff0c;10几年前&#xff0c;我自学单片机时&#xff0c;也一样。 想通过学习&#xff0c;找一份体面点的工作&#xff0c;又害怕辛辛苦苦学出来&#xff0c;找不到工作。 好在&#xff0c;当初执行力&#xff0c;还算可以&#xff0c;自…...

探索设计模式:观察者模式

探索设计模式&#xff1a;观察者模式 &#x1f9d0;观察者模式简介:gem:核心概念:rainbow:观察者模式的优点:truck:实现步骤1. 定义主题接口2. 实现观察者接口3. 具体主题实现4. 具体观察者实现5. 调用 :triangular_flag_on_post:总结 在实际开发过程中&#xff0c;设计模式的作…...

gradio之持续输入,持续输出(流式)

流式输出yield,比如一个输出控件&#xff0c;想要实时显示内容&#xff0c;用return for循环一次就返回去了。而用yield会持续更新往下执行 for i in range(length):time.sleep(8)yield 总共str(length)条语料&#xff0c;已运行str(i1)条 在Gradio中&#xff0c;某些组件&am…...

Git 常用命令指南:从入门到精通

文章目录 前言1. 初始化一个Git仓库2. 克隆远程仓库3. 查看仓库状态4. 添加文件到暂存区5. 提交代码6. 推送到远程仓库7. 拉取远程仓库的更改8. 分支管理9. 查看提交历史10. 回退到某个版本结语 前言 如果你是一位开发者或者对代码感兴趣&#xff0c;那么你一定听说过Git。Git…...

Camera驱动 汇总表【小驰行动派】

在做Camera BringUp的时候&#xff0c;如果有已经点亮过的驱动源码&#xff0c;对我们的帮助将会非常的大&#xff0c;可以大大加快我们点亮进度。 所以我决定整理汇总接触过得Camera驱动信息。如果你刚好有需要&#xff0c;可以加我薇咨询&#xff08;该资料整理比较花时间&a…...

SSRS rdlc报表 九 在.net core中使用RDLC报表

开发环境 vs 2022企业版 SqlServer数据库 Win11 前言 rdlc报表在aspx中集成的很好,很容易实现,并且功能强大,但随着技术的发展,aspx慢慢的被淘汰,现在已经发展到.net8了,aspx基本上很少用,出的新框架基本上也都是前后端分离,没了aspx的控件加持,rdlc这么厉害的报…...

力扣(2024.08.10)

1. 222&#xff1a;完全二叉树的节点个数 # Definition for a binary tree node. # class TreeNode: # def __init__(self, val0, leftNone, rightNone): # self.val val # self.left left # self.right right class Solution:def countNodes(…...

C++实现分布式网络通信框架RPC(3)--rpc调用端

目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中&#xff0c;我们已经大致实现了rpc服务端的各项功能代…...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​&#xff0c;覆盖应用全生命周期测试需求&#xff0c;主要提供五大核心能力&#xff1a; ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…...

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出&#xff1a;JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中&#xff0c;随机数的生成看似简单&#xff0c;却隐藏着许多玄机。无论是生成密码、加密密钥&#xff0c;还是创建安全令牌&#xff0c;随机数的质量直接关系到系统的安全性。Jav…...

CMake基础:构建流程详解

目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU&#xff1a;如何让RNN变得更聪明&#xff1f; 在深度学习的世界里&#xff0c;循环神经网络&#xff08;RNN&#xff09;以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而&#xff0c;传统RNN存在的一个严重问题——梯度消失&#…...

linux arm系统烧录

1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 &#xff08;忘了有没有这步了 估计有&#xff09; 刷机程序 和 镜像 就不提供了。要刷的时…...

【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表

1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

如何将联系人从 iPhone 转移到 Android

从 iPhone 换到 Android 手机时&#xff0c;你可能需要保留重要的数据&#xff0c;例如通讯录。好在&#xff0c;将通讯录从 iPhone 转移到 Android 手机非常简单&#xff0c;你可以从本文中学习 6 种可靠的方法&#xff0c;确保随时保持连接&#xff0c;不错过任何信息。 第 1…...

【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】

1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件&#xff08;System Property Definition File&#xff09;&#xff0c;用于声明和管理 Bluetooth 模块相…...