C++内存管理(候捷)第一讲 笔记

内存分配的每一层面

在这里插入图片描述
applications可以调用STL,里面会有allocator进行内存分配;也可以使用C++ 基本工具primitives,比如new, new[], new(), ::operator new();还可以使用更底层的malloc和free分配和释放内存。最底层的是系统调用,比如HeapAlloc,VirtualAlloc
在这里插入图片描述
在C中,malloc 和 free 是标准库函数,不涉及构造函数和析构函数,只是简单的内存分配和释放

int *ptr = (int *)malloc(sizeof(int));
free(ptr);

在C++中,new 和 delete 不仅仅是内存分配和释放的操作符,还会处理对象的构造和析构

四个层面的基本用法

在这里插入图片描述
malloc和 ::operator new()是完全一样的效果
allocator()是创建一个临时对象来调用非static函数
在这里插入图片描述
__GNUC__版本4.9的分配器

基本构件之一new delete expression上

在这里插入图片描述
由于有分配内存,因此要try catch考虑内存分配失败时如何处理
new的过程:1.分配内存 2.指针转型 3.调用构造函数

在指定内存上创建对象使用placement new:new (pointer) Type(initializer);

void* memory = operator new(sizeof(MyClass)); // 分配内存
MyClass* obj = new (memory) MyClass(/* constructor arguments */); // 在指定内存位置创建对象
void* memory = operator new[](sizeof(MyClass) * 5); // 分配数组内存
MyClass* objArray = new (memory) MyClass[5]; // 在数组内存中创建对象

_callnewh 不是 C++ 标准中的函数,而是可能是用户定义的一个函数。通常情况下,这类函数的名字以 _new_handler 结尾,用于处理内存分配失败的情况。
在 C++ 中,当 new 表达式无法分配所需的内存时,会调用用户指定的 new_handler 函数。new_handler 是一个函数指针,指向一个用户定义的函数,其原型通常为

typedef void (*new_handler)();

这个函数可以尝试释放内存、扩大内存池,或者执行其他操作来尝试解决内存不足的问题。如果 new_handler 能够成功处理内存不足的情况,返回;如果不能处理,可以选择抛出异常或者终止程序

基本构件之一new delete expression中

在这里插入图片描述
使用定位 new 运算符后,必须手动调用对象的析构函数来释放资源,否则可能导致内存泄漏

obj->~MyClass(); // 手动调用析构函数
operator delete(memory); // 手动释放内存

delete的动作:先调用析构函数,然后释放内存。
operator delete里调用free

基本构件之一new delete expression下

在这里插入图片描述
ctor和dtor直接调用的测试

Array new

在这里插入图片描述
cookie记录的是下面一块的长度。malloc分配的时候会额外带上一块cookie的信息,供给free释放
在这里插入图片描述
测试
在这里插入图片描述
vc6下malloc new int[10]内存布局:灰色表示具体数据,橙色是debug模式下添加的内存。上面和最下面的两个0x61(61H)是cookie,记录整体内存分配的大小。61H实际上是60H,表示内存分配的大小,后面1H意思是占用最后一位,表示内存分配出去。浅蓝色的pad表示补齐,填补到16的倍数
在这里插入图片描述
在这里插入图片描述

placement new

在这里插入图片描述
placement new允许我们将对象建构在已经分配好的内存中

Complex* pc = new(buf)Complex(1, 2);这句话会被编译器转换为,分别调用operator new(需要第二个参数,表示位置,这个函数只是传回这个位置,不再分配内存),指针转型,调用构造函数

重载

在这里插入图片描述
new是表达式,不可改变不可重载。会调用 operator new,全局(可重载但少见)或者成员函数(可重载)
在这里插入图片描述
容器里把构造函数和析构函数包装在 construct()和destroy(),内存分配动作allocate()和deallocate()会走入分配器allocator中处理

容器分配内存的一般途径:容器使用分配器,在这里插入图片描述
分配器调用 ::operator new 和 ::operator delete,底层可能调用 malloc 和 free:
在这里插入图片描述
重载全局的::operator new 和::operator delete
在这里插入图片描述
在一个类中重载operator new和operator delete。编译器会自动调用
通常会加static,因为调用的地方通常在创建对象的过程中,无法通过对象来调用一般函数
在这里插入图片描述

重载示例

在这里插入图片描述
在这里插入图片描述
重载示例
有虚函数只是把大小放大了,一个12,一个16
在GNU C++4.9版本中构造是从上到下,析构是从下到上
在这里插入图片描述
使用全局new,delete示例
在这里插入图片描述
placement new的重载第一参数必须是size_t类型,接受类的大小,会传入Foo的大小。其余的参数就是括号里的参数
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
平常使用的string,就是个typedef ,define basic_string。重载了operator new。每次创建时也额外分配字符串大小的内存

Per class allocator

在这里插入图片描述
内存池:用malloc分配一大块(内存池),然后分成小块,减少malloc的调用次数。另外减少cookie的用量。
在Screen类中引入一个指针next,它的大小是4B,用于串联链表
delete操作,把指针p回收到单向链表中,放到链表的头指针位置
在这里插入图片描述
左边间隔8表示每个Screen对象内存分配的大小为8B,说明每个Screen分配的时候没有cookie。
右边间隔16,表示每个Screen对象内存分配的大小为16B,这是因为对象分配的时候上下加了cookie,最上面和最下面的cookie大小共为8B

Per class allocator 2

在这里插入图片描述
struct AirplaneRep,由于对齐,5B会变成8B
union 是一种特殊的数据结构,可以看作同一个东西,用不同的名称/不同的角度去看待。
上述例子用指针去看待union时,只看8个字节的前4个字节

通过union借用内存块的前4个字节当作指针
在这里插入图片描述
delete没有free,只是把区块回收到链表,并未把内存还给操作系统,链表可能会越来越长,超过512块

Static allocator

从软件工程的角度看,上面的operator new和operator delete对于不同 类都要重载,明显不是一个好的解法,因此将allocator抽象成一个类。

具体的类进行内存分配的时候,只需要调用allocator即可
在这里插入图片描述
在这里插入图片描述
嵌入式指针embedded pointer:借用A对象所占用的内存空间中的前4个字节,这4个字节用来 链住这些空闲的内存块;但是,一旦某一块被分配出去,那么这个块的 前4个字节 就不再需要。因此类A对象的sizeof必须不小于4字节

上述例子定义一个类型obj,不放在外部,污染全局变量。struct里放了一个指针,它的大小为4个字节。这个指针的值,存着下一个内存的地址。由于这里只需要指针,所以union可以不使用。
在这里插入图片描述
由于上面的CHUNK设置为5,每5个对象的内存空间是连续的(间隔都是一个对象的大小),而每个大块之间是不连续的。

Macro for static allocator

在这里插入图片描述
把allocator的部分拿出来用宏来定义
宏是预处理指令,用于在编译过程中执行文本替换。宏通常通过 #define 关键字定义,并在代码中通过宏名称来调用。它们是一种简单的文本替换机制,可以用于创建常量、函数替代、条件编译等。
在宏定义的末尾使用反斜杠是为了告诉编译器该宏定义将在下一行继续。如果在宏定义的最后一行没有使用反斜杠,那么编译器会认为宏定义结束了

版本1:指针,版本2:embedded pointer,版本3:抽取内存的动作到单一class Allocator 版本4:alloctator通过宏抽取出来
在这里插入图片描述
标准库中的allocator
其中一种分配器有16条自由链表,来应对不同大小的块分配,不同的大小的类对象,分配到不同的链表中

New Handler

在这里插入图片描述
new handler 是一个函数指针,当 new 操作符无法分配所需的内存时,会调用与之关联的 new handler
new handler 是全局的,一旦设置,会在程序的生命周期内一直有效,直到被其他 set_new_handler 覆盖
在这里插入图片描述
new handler的例子
在这里插入图片描述
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

实现好友关注功能的Feed流设计

摘要 在社交网络应用中,Feed流是展示好友动态的核心功能。本文将探讨如何设计一个Feed流系统,以实现好友关注和动态展示的功能。 1. Feed流的基本概念 Feed流是用户在社交网络中获取信息的一种方式,通常按照时间顺序展示好友或感兴趣的用户…

Maven Archetype 自定义项目模板:高效开发的最佳实践

文章目录 前言一、Maven Archetype二、创建自定义 Maven Archetype三、定制 Archetype 模板四、手动创建 Archetype 模板项目五、FAQ5.1 如何删除自定义的模板5.2 是否可以在模板中使用空文件夹 六、小结推荐阅读 前言 在软件开发中,标准化和快速初始化项目结构能够…

调用asyncio.to_thread后上下文依然一致吗

使用Python的asyncio时,可以把一个同步的函数放到线程池中执行从而避免这个函数阻塞asyncio自身的事件循环。比如可以把requests库的请求放进去 async def to_thread_do_request(url):return await asyncio.to_thread(requests.get, url)这个to_thread_do_request方…

14-20 Vision Transformer用AI的画笔描绘新世界

概述 毫无疑问,目前最受关注且不断发展的最重要的主题之一是使用人工智能生成图像、视频和文本。大型语言模型 (LLM) 已展示出其在文本生成方面的卓越能力。它们在文本生成方面的许多问题已得到解决。然而,LLM 面临的一个主要挑战是它们有时会产生幻觉反应。 最近推出的新模…

分布式计算、异构计算与算力共享

目录 算力 算力共享的技术支撑 云计算技术 边缘计算技术 区块链技术 分布式计算、异构计算与算力共享 分布式计算:计算力的“集团军作战” 异构计算:计算力的“多兵种协同” 算力共享:计算力的“共享经济” 深入融合,共创计算新纪元 算力共享对科研领域的影响 …

openmetadata1.3.1 自定义连接器 开发教程

openmetadata自定义连接器开发教程 一、开发通用自定义连接器教程 官网教程链接: 1.https://docs.open-metadata.org/v1.3.x/connectors/custom-connectors 2.https://github.com/open-metadata/openmetadata-demo/tree/main/custom-connector (一&…

Matplotlib 文本

可以使用 xlabel、ylabel、text向图中添加文本 mu, sigma 100, 15 x mu sigma * np.random.randn(10000)# the histogram of the data n, bins, patches plt.hist(x, 50, densityTrue, facecolorg, alpha0.75)plt.xlabel(Smarts) plt.ylabel(Probability) plt.title(Histo…

Qt读取ini格式配置文件的类设计

目录 1.引言 2.QSettings 2.1.功能特点 2.2.基本用法 3.读取ini文件配置通用类设计 3.1.设计要点 3.2.完整实现 3.3.调用方法 4.总结 1.引言 在编写应用程序的时,有些参数需要用户配置,那么这些参数就涉及到存储了,单从存储来讲&…

git 还原被删除的分支

在多人项目开发中,有一次碰到忘记合并到master分支了,直接就把开发分支给删除了,现在记录下怎么还原被删除的分支 必须保证删除的分支之前已经被推送到了远程仓库 # 找出被删除分支的最后一个提交的哈希值 git reflog show# 找到提交哈希值…

2024/07/04

1、梳理笔记(原创) 2、终端输入一个日期&#xff0c;判断是这一年的第几天 scanf("%d-%d-%d",&y,&m,&d); 闰年2月29天&#xff0c;平年2月28天 #include<stdio.h> int main(int argc, char const *argv[]) {int y0,m0,d0;printf("please ente…

析构函数和拷贝构造函数

文章目录 析构函数1.析构函数的定义&#xff1a;2.析构函数的语法&#xff1a;3.析构函数的特性&#xff1a; 拷贝构造函数1.拷贝构造函数的定义&#xff1a;2.拷贝构造函数的语法3.拷贝构造函数的特性(1)拷贝构造函数是构造函数的一个重载形式**(这个其实也很好理解&#xff0…

鸿蒙开发设备管理:【@ohos.thermal (热管理)】

热管理 该模块提供热管理相关的接口&#xff0c;包括热档位查询及注册回调等功能。 说明&#xff1a; 本模块首批接口从API version 8开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。开发前请熟悉鸿蒙开发指导文档&#xff1a;gitee.com/li-shi…

如何实现图片垂直旋转90度的问题

非常简单的问题&#xff0c;一串代码就可以解决。复制修改一下就可以直接使用&#xff0c;一个简单的小demo。写项目的时候需要写的功能&#xff0c;不到二十行代码就可以实现。 <html> <head><title>旋转图片</title><meta http-equiv"Conte…

Land survey boundary report (template)

Land survey boundary report (template) 土地勘测定界报告&#xff08;模板&#xff09;.doc

【高校科研前沿】南京地理与湖泊研究所博士后夏凡为第一作者在环境科学与水资源领域Top期刊发文:钙对云南洱海溶解有机质与浮游细菌相互作用的调控作用

文章简介 论文名称&#xff1a;Calcium regulates the interactions between dissolved organic matter and planktonic bacteria in Erhai Lake, Yunnan Province, China 第一作者及单位&#xff1a;夏凡&#xff08;博士后|中国科学院南京地理与湖泊研究所&#xff09; 通讯…

Git指令

一 参考&#xff1a;https://zhuanlan.zhihu.com/p/389814854 1.clone远程仓库 git clone https://git.xiaojukeji.com/falcon-mg/dagger.git 2.增加当前子目录下所有更改过的文件至index git add . 3.提交并备注‘xxx’ git commit -m ‘xxx’ 4.显示本地分支 git branch 5.显…

【pytorch13】激活函数及梯度

什么是激活函数 计算机科学家借鉴生物的神经元机制发明了计算机上的模型&#xff0c;这个模型与生物的神经元非常类似 激活的意思就是z变量要大于0&#xff0c;这一个节点才会激活&#xff0c;否则就会处于睡眠状态不会输出电平值 该激活函数在z0处不可导&#xff0c;因此不能…

Asp .Net Core 系列:基于 Castle DynamicProxy + Autofac 实践 AOP 以及实现事务、用户填充功能

文章目录 什么是 AOP &#xff1f;.Net Core 中 有哪些 AOP 框架&#xff1f;基于 Castle DynamicProxy 实现 AOPIOC中使用 Castle DynamicProxy实现事务管理实现用户自动填充 什么是 AOP &#xff1f; AOP&#xff08;Aspect-Oriented Programming&#xff0c;面向切面编程&a…

OpenCV——把YOLO格式的图片目标截图,并按目标类别保存

import os import cv2def get_class_folder(catagetory,class_id, base_folder):# 根据类别ID创建文件夹路径class_folder os.path.join(base_folder, catagetory[int(class_id)])if not os.path.exists(class_folder):os.makedirs(class_folder)return class_folderdef crop_…

VPN是什么?

VPN&#xff0c;全称Virtual Private Network&#xff0c;即“虚拟私人网络”&#xff0c;是一种在公共网络&#xff08;如互联网&#xff09;上建立加密、安全的连接通道的技术。简单来说&#xff0c;VPN就像是一条在公共道路上铺设的“秘密隧道”&#xff0c;通过这条隧道传输…