五、C++内存管理机制 —— primitives(侯捷)

侯捷 C++八部曲笔记汇总 - - - 持续更新 ! ! !
一、C++ 面向对象高级开发
1、C++面向对象高级编程(上)
2、C++面向对象高级编程(下)
二、STL 标准库和泛型编程
1、分配器、序列式容器
2、关联式容器
3、迭代器、 算法、仿函数
4、适配器、补充
三、C++ 设计模式
四、C++ 新标准
五、C++ 内存管理机制
1、primitives
2、malloc/free
3、std::allocator
4、other allocators
5、loki::allocator
六、C++ 程序的生前和死后

五、C++内存管理机制 —— 基础工具 primitives(侯捷)

  • new、delete 表达式
    • 基本用法
    • array new、array delete
    • placement new
  • operator new()、operator delete()函数
    • 重载 ::operator new / ::operator delete
    • 重载 operator new() / operator delete()

👉 该课程能让你:从平地到万丈高楼!—— 侯捷
👉 做到:心中自有丘壑!
💪 源码之前,了无秘密!

所有内存管理的最终动作都要跑到malloc去,所以malloc的效率至关重要。

  • 即,最高阶是使用STL中的内存分配器,而STL的内存分配器实现是通过newnew[]new()等较为低阶的函数,但终归会到mallocfree这两种C函数上来!
  • 一般不会到最下面操作系统层次,不然程序不具有可移植性!

C++内存使用途径:
在这里插入图片描述

C++内存分配的基本工具如下:
在这里插入图片描述
🏃 四个层面使用栗子:

void* p1 = malloc(512); //512 bytes
free(p1);

complex<int>* p2 = new complex<int>; //one object
delete p2;

void* p3 = ::operator new(512);  //512 bytes (低层就是调用malloc)
::operator delete(p3); //(低层就是调用free)

//以下使用C++ 标准库提供的allocators。
//GNUC2.9  (以下函数为static,定要通过object调用)
void* p4 = alloc::allocate(512);//分配512bytes
alloc::deallocate(p4, 512);

//GNUC4.9  (以下函数为non-static,定要通过object调用)
void* p5 = allocator<int>().allocate(5); //分配5个int
allocator<int>().deallocate((int*)p5, 5);//归还个数也要告诉它

new、delete 表达式

基本用法

⭐️ new的过程分为三步:

  1. 分配内存(指定类大小的空间):new->operator new->malloc
  2. 将指针转化为对应的类类型
  3. 通过指针调用构造函数

在这里插入图片描述
在上图右上角operator new的源码中:

  • malloc没有成功时(一般很少出现),会调用你设定的函数new handler, 在这里面释放可以释放的内存,然后再调用malloc看是否成功;
  • std::nothrow_t& _THROW0()参数,表示这个函数不抛异常,取而代之的是返回一个空指针,用户通过判断是否为空指针来判断是否分配成功。

👉 new handler

  • operator new没有能力为你分配出你所申请的memory,会抛出一个bad_alloc的异常。抛出异常之前会先(不止一次)调用一个可由用户指定的handler
typedef void(*new_handler)();
new_handler set_new_handler(new_handler p) throw();

这个new handler一般做两件事情:

  1. 让更多的内存可用;
  2. 调用abort()或者exit()

⭐️ delete的过程:

  1. 先调用析构函数,对象本身的内存就会被释放掉,对象也就死亡了;
  2. 然后释放内存delete -> operator delete -> free

在这里插入图片描述

构造函数不能被直接调用,析构函数可以被直接调用!

在这里插入图片描述

array new、array delete

⭐️ array new是分配一个对象数组:

  • 通常容易犯得一个错误是在delete的时候忘记在delete后面加 []导致内存泄漏的问题

在这里插入图片描述

正如上图所说的:

  • 对于类中没有指针的类,不加 [] 可能问题不大,因为没有指针的类析构函数本来也就没有什么大的作用;
  • 但是,如果有指针,忘记写 [] ,那么 delete 只会触发一次析构函数delete掉一个指针指向的内存,其他指针指向的内存就会泄露。
    • 如上图的 psa 析构,str2str3指向的地址会发生内存泄漏(析构的顺序依编译器而定)。

使用例子:

在这里插入图片描述

👉 没有办法直接调用构造函数设初值,只能绕个弯使用placement new来设初值,形式如下:

//定点的new
new(tem)A(i);			//tem是一个指针

下面两张图分别表示有指针没指针的对象数组分配内存的区别:

在这里插入图片描述
在这里插入图片描述

对于分配一个对象数组,他会把数组的大小也放到存放对象数组的内存块的开头:

  • 如果在delete内存的时候不加 [],编译器会把他当成一个一般的指针,指向一块对象;
  • 它按照一块对象的方式来解析布局,但是存储的是3块,整个布局就乱掉了,就会报错!

placement new

array new调用的是类的默认构造函数,还需要对数组中的对象进行真正的构造,这就需要placement new允许我们将对象分配在已经构建的内存中

placement new 就等同于调用构造函数。他不会进行内存分配,具体过程如下:

  1. 调用重载的operator new,和上面的形式不一样,还传入了第二个参数buf定点),用于返回已经分配好的内存;
  2. 转型;
  3. 调用构造函数
    在这里插入图片描述

operator new()、operator delete()函数

  • 一般在类里可重载;
  • 也可以重载全局::operator new / ::operator delete,但很少,不然可能影响很大!

在这里插入图片描述
容器自己也有一套重载:

在这里插入图片描述

重载 ::operator new / ::operator delete

⭐️ 重载全局的:

在这里插入图片描述

⭐️ 在类中重载::operator new / ::operator delete更有用(array new / array delete重载也是一样的方法):

在这里插入图片描述
在这里插入图片描述

在类里重载operator newoperator delete前面一般要加上static(静态的):

  • 因为在创建对象的时候,对象还没有创建成功,因此是无法通过对象来调用一般的函数;
  • 所以必须是静态的,这样才能不通过对象就能调用起来。

在这里插入图片描述

重载 operator new() / operator delete()

⭐️ 我们可以重载class member operator new()的前提是

  • 每一个版本的声明都必须有独特的参数列,其中第一个参数必须是size_t,其余参数以 new 所制定的 placement arguments为初值。

出现于new (…)小括号内的便是所谓的 placement arguments。形式例如:

//placement new
Foo* pf = new(300, 'c') Foo;

在这里插入图片描述
⭐️ 我们可以重载class member operator delete()

  • 但它们绝不会被delete调用;
  • 只有当new 所调用的 ctor 抛出 exception,才会调用这些重载版的 operator delete()
  • 它只可能这样被调用,主要用来归还未能完全创建成功的object所占用的memory

在这里插入图片描述

注:仅供学习参考,如有不足,欢迎指正!👍👍👍

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/15926.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

微服务---分布式事务Seata(XA,AT,TCC,SAGA模式基本使用)

分布式事务 1.分布式事务问题 1.1.本地事务 本地事务&#xff0c;也就是传统的单机事务。在传统数据库事务中&#xff0c;必须要满足四个原则&#xff1a; 1.2.分布式事务 分布式事务&#xff0c;就是指不是在单个服务或单个数据库架构下&#xff0c;产生的事务&#xff0c…

2023牛客五一集训派对day2部分题解

D Duration DDuration 题目大意 给你两个 AA:BB:CC 格式的时间&#xff0c;请你计算它们直接的时间插值&#xff08;秒&#xff09; 解题思路 模拟 代码示例 #include<bits/stdc.h> using namespace std;int h, m, s;int main(){scanf("%d:%d:%d", &…

跨域问题解决方案

什么是跨域问题 跨域问题本质上是由浏览器的同源策略造成的&#xff0c;是浏览器对javascript施加的安全限制。 它指的服务A对服务B发起请求时&#xff0c;如果传输协议&#xff08;http、https&#xff09;、ip 地址&#xff08;域名&#xff09;、端口号有任意一个不同&…

一键轻松拥有自己专属的 ChatGPT 网页版,搭建一个私人的可随时随地访问的ChatGPT网站

前言 ChatGPT是一种基于Transformer架构的自然语言处理模型&#xff0c;由OpenAI开发。GPT是“Generative Pre-trained Transformer”的缩写&#xff0c;意为“预训练生成式Transformer模型”。 ChatGPT模型是一种无监督学习模型&#xff0c;它可以在大规模文本数据上进行预训…

『Linux』第九讲:Linux多线程详解(二)_ 线程控制

「前言」文章是关于Linux多线程方面的知识&#xff0c;上一篇是 Linux多线程详解&#xff08;一&#xff09;&#xff0c;今天这篇是 Linux多线程详解&#xff08;二&#xff09;&#xff0c;讲解会比较细&#xff0c;下面开始&#xff01; 「归属专栏」Linux系统编程 「笔者」…

【2023华中杯数学建模】B 题 小学数学应用题相似性度量及难度评估详细建模方案及实现代码

更新时间&#xff1a;2023-5-1 14:00 1 题目 B 题 小学数学应用题相似性度量及难度评估 某 MOOC 在线教育平台希望能够进行个性化教学&#xff0c;实现用户自主学习。在用户学习时&#xff0c;系统从题库中随机抽取若干道与例题同步的随堂测试题&#xff0c;记录、分析学生的学…

【常用算法】进制转换

目录 1. 二进制数、八进制数、十六进制数转换为十进制数 2. 十进制数转换为二进制数、八进制数、十六进制数 3. 二进制数和十六进制数的相互转换 4. 使用电脑计算器进行进制转换 1. 二进制数、八进制数、十六进制数转换为十进制数 十进制数的每一位都是10的指数幂。如&…

Python 中如何实现自动导入缺失的库?

在编写 Python 项目的时候&#xff0c;我们经常会遇到导入模块失败的错误&#xff1a; ImportError: No module named xxx或者ModuleNotFoundError: No module named xxx 导入失败&#xff0c;通常分为两种&#xff1a;一种是导入自己写的模块&#xff08;即以 .py 为后缀的文件…

每天一道算法练习题--Day17 第一章 --算法专题 --- ----------布隆过滤器

场景 假设你现在要处理这样一个问题&#xff0c;你有一个网站并且拥有很多访客&#xff0c;每当有用户访问时&#xff0c;你想知道这个 ip 是不是第一次访问你的网站。 hashtable 可以么 一个显而易见的答案是将所有的 IP 用 hashtable 存起来&#xff0c;每次访问都去 hash…

微软开源AI修图工具让老照片重现生机

GitHub - microsoft/Bringing-Old-Photos-Back-to-Life: Bringing Old Photo Back to Life (CVPR 2020 oral) 支持划痕修复&#xff0c;以及模型训练。 Old Photo Restoration (Official PyTorch Implementation) Project Page | Paper (CVPR version) | Paper (Journal vers…

Mysql第二章 多表查询的操作

这里写自定义目录标题 一 外连接与内连接的概念sql99语法实现 默认是内连接sql99语法实现左外连接&#xff0c;把没有部门的员工也查出来sql99语法实现右外连接&#xff0c;把没有人的部门查出来sql99语法实现满外连接&#xff0c;mysql不支持这样写mysql中如果要实现满外连接的…

【Java数据结构】——第九节.向上建堆和向下建堆的区别

作者简介&#xff1a;大家好&#xff0c;我是未央&#xff1b; 博客首页&#xff1a;未央.303 系列专栏&#xff1a;Java初阶数据结构 每日一句&#xff1a;人的一生&#xff0c;可以有所作为的时机只有一次&#xff0c;那就是现在&#xff01;&#xff01;&#xff01; 文章目…

Android jetpack Compose之约束布局

概述 我们都知道ConstraintLayout在构建嵌套层级复杂的视图界面时可以有效降低视图树的高度&#xff0c;使视图树扁平化&#xff0c;约束布局在测量布局耗时上比传统的相对布局具有更好的性能&#xff0c;并且约束布局可以根据百分比自适应各种尺寸的终端设备。因为约束布局确…

下载——安装——使用FinalShell

下载——安装——使用FinalShell FinalShell简介&#xff1a;下载&#xff1a;使用&#xff1a; FinalShell简介&#xff1a; FinalShell是一款免费的国产的集SSH工具、服务器管理、远程桌面加速的软件&#xff0c;同时支持Windows&#xff0c;macOS&#xff0c;Linux&#xf…

No.050<软考>《(高项)备考大全》【冲刺4】《软考之 119个工具 (2)》

《软考之 119个工具 &#xff08;2&#xff09;》 21.检查:22.偏差分析:23.滚动式规划:24.紧前关系绘图法(PDM):25.确定依赖关系:26.时间提前量与滞后量:28.发布的估算数据:29.自下而上估算:30.项目管理软件:31.储备分析:32.类比估算:33.参数估算:34.三点估算:35.进度网络分析:…

JS实现拼音(字母)匹配(搜索)汉字(姓名)

这就是个模糊查询&#xff0c;我们平常做的都是直接输入汉字去把对应的值过滤出来&#xff0c;但我还真是第一次通过拼音去查询&#xff08;当然不只是拼音&#xff0c;汉字也是可以的&#xff09;&#xff0c;以前还真没注意这个。唉&#xff0c;这可咋搞&#xff0c;我怎么知…

使用Statsmodel进行假设检验和线性回归

如果你使用 Python 处理数据&#xff0c;你可能听说过 statsmodel 库。Statsmodels 是一个 Python 模块&#xff0c;它提供各种统计模型和函数来探索、分析和可视化数据。该库广泛用于学术研究、金融和数据科学。在本文中&#xff0c;我们将介绍 statsmodel 库的基础知识、如何…

(七)ArcCatalog应用基础——图层操作与数据输出

&#xff08;七&#xff09;ArcCatalog应用基础——图层操作与数据输出 目录 &#xff08;七&#xff09;ArcCatalog应用基础——图层操作与数据输出 1.地图与图层操作1.1创建图层1.2设置文件特征1.3保存独立的图层文件 2.地理数据输出2.1输出为Shapefile2.2输出为Coverage2.3属…

笔记本电脑没有声音了怎么恢复

笔记本电脑 在使用的过程中&#xff0c;突然没有声音的话&#xff0c;对于人们来说会很麻烦。那么笔记本电脑没有声音了怎么恢复呢?下面小编为大家整理了笔记本电脑没有声音的恢复方法&#xff0c;一起来看看吧。 方法/步骤&#xff1a; 方法一&#xff1a;网络适配器检查音频…

UE5实现建筑剖切效果

文章目录 1.实现目标2.实现过程2.1 材质参数集2.2 材质遮罩函数2.3 更新Box3.参考资料1.实现目标 基于BoxMask材质节点,在UE5中实现建筑物的剖切效果,GIF动图如下: 2.实现过程 实现原理与之前“BoxMask实现建筑生长效果”的原理相同,都是基于BoxMask材质节点实现。 具体实…