C++ 内存分配和管理(八股总结)
C++是如何做内存管理的(有哪些内存区域)?
(1)堆,使用malloc、free动态分配和释放空间,能分配较大的内存;
(2)栈,为函数的局部变量分配内存,能分配较小的内存;
(3)全局/静态存储区,用于存储全局变量和静态变量;
(4)常量存储区,专门用来存放常量;
(5)自由存储区:通过new和delete分配和释放空间的内存,具体实现可能是堆或者内存池。
补充:堆是C和操作系统的术语,自由存储区是C++的术语,指的是通过new和delete动态分配和释放对象的抽象概念;基本上C++也会用堆区实现自由存储,但程序员可以通过重载操作符,改用其他内存实现自由存储,比如全局变量做的对象池。
堆和栈的内存有什么区别?
(1)堆中的内存需要手动申请和手动释放,栈中内存是由OS自动申请和自动释放;
(2)堆能分配的内存较大(4G(32位机器)),栈能分配的内存较小(1M);
(3)在堆中分配和释放内存会产生内存碎片,栈不会产生内存碎片;
(4)堆的分配效率低,栈的分配效率高;
(5)堆地址从低向上,栈由高向下。
C++和C分别使用什么函数来做内存的分配和释放?有什么区别,能否混用?
C使用malloc/free,C++使用new/delete,前者是C语言中的库函数,后者是C++语言的运算符,对于自定义对象,malloc/free只进行分配内存和释放内存,无法调用其构造函数和析构函数,只有new/delete能做到,完成对象的空间分配和初始化,以及对象的销毁和释放空间,不能混用,具体区别如下:
(1)new分配内存空间无需指定分配内存大小,malloc需要;
(2)new返回类型指针,类型安全,malloc返回void*,再强制转换成所需要的类型;
(3)new是从自由存储区获得内存,malloc从堆中获取内存;
(4)对于类对象,new会调用构造函数和析构函数,malloc不会(核心)。
什么是内存对齐(字节对齐),为什么要做内存对齐,如何对齐?
(1)内存对齐的原因:关键在于CPU存取数据的效率问题。为了提高效率,计算机从内存中取数据是按照一个固定长度的。比如在32位机上,CPU每次都是取32bit数据的,也就是4字节;若不进行对齐,要取出两块地址中的数据,进行掩码和移位等操作,写入目标寄存器内存,效率很低。内存对齐一方面可以节省内存,一方面可以提升数据读取的速度;
(2)内容:内存对齐指的是C++结构体中的数据成员,其内存地址是否为其对齐字节大小的倍数。
(3)对齐原则:1)结构体变量的首地址能够被其最宽基本类型成员的对齐值所整除;2)结构体内每一个成员的相对于起始地址的偏移量能够被该变量的大小整除;3)结构体总体大小能够被最宽成员大小整除;如果不满足这些条件,编译器就会进行一个填充(padding)。
(4)如何对齐**:**声明数据结构时,字节对齐的数据依次声明,然后小成员组合在一起,能省去一些浪费的空间,不要把小成员参杂声明在字节对齐的数据之间。
#pragma pack 指令:这是一个编译器指令,用于控制结构体或联合体中成员的对齐。例如,#pragma pack(push, 1) 可以设置对齐为1字节,而 #pragma pack(pop) 则恢复到之前的对齐设置。
#pragma pack(push, 1)
struct MyStruct {char a; // 1 byteint b; // 4 bytes
};
#pragma pack(pop)
C++11 alignas 关键字:C++11 引入了 alignas 关键字,允许程序员显式指定变量或类型的最小对齐要求。
struct alignas(16) MyStruct {char a;int b;
};
这里,MyStruct 的实例将保证16字节对齐。
malloc、calloc、realloc、alloca
- malloc:申请指定字节数的内存。申请到的内存中的初始值不确定。
- calloc:为指定长度的对象,分配能容纳其指定个数的内存。申请到的内存的每一位(bit)都初始化为 0。
- realloc:更改以前分配的内存长度(增加或减少)。当增加长度时,可能需将以前分配区的内容移到另一个足够大的区域,而新增区域内的初始值则不确定。
- alloca:在栈上申请内存。程序在出栈的时候,会自动释放内存。但是需要注意的是,alloca 不具可移植性, 而且在没有传统堆栈的机器上很难实现。alloca 不宜使用在必须广泛移植的程序中。C99 中支持变长数组 (VLA),可以用来替代 alloca。
在 C++ 中,malloc、calloc、realloc 和 alloca 是动态内存分配函数,主要用于在运行时分配和管理内存。下面对它们分别进行定义、主要用途和区别分析。
1. malloc(Memory Allocation)
定义
malloc 函数用于分配指定大小的内存块,返回一个指向该内存块的指针,初始值为未定义(即未初始化)。
用途
- 用于在堆中分配内存。
- 适合需要明确大小但不需要初始化的内存场景。
示例代码
#include <cstdlib>
#include <iostream>int main() {int* ptr = (int*)malloc(5 * sizeof(int)); // 分配 5 个整型大小的内存块if (ptr == nullptr) {std::cout << "Memory allocation failed\n";return 1;}for (int i = 0; i < 5; ++i) {ptr[i] = i + 1; // 手动初始化}for (int i = 0; i < 5; ++i) {std::cout << ptr[i] << " ";}std::cout << "\n";free(ptr); // 释放内存return 0;
}
输出
1 2 3 4 5
2. calloc(Contiguous Allocation)
定义
calloc 用于分配指定数量的内存块,并将所有分配的内存初始化为零。
用途
- 适合需要分配连续的内存块且初始化为零的场景。
- 提高内存分配后的安全性。
示例代码
#include <cstdlib>
#include <iostream>int main() {int* ptr = (int*)calloc(5, sizeof(int)); // 分配 5 个整型大小的内存块并初始化为 0if (ptr == nullptr) {std::cout << "Memory allocation failed\n";return 1;}for (int i = 0; i < 5; ++i) {std::cout << ptr[i] << " "; // 输出已初始化为 0 的值}std::cout << "\n";free(ptr); // 释放内存return 0;
}
输出
0 0 0 0 0
3. realloc(Reallocation)
定义
realloc 用于调整之前分配的内存大小。它可能会移动原内存块到新的位置,返回新内存块的指针。
用途
- 动态调整已分配内存大小。
- 避免重新分配和手动复制数据。
示例代码
#include <cstdlib>
#include <iostream>int main() {int* ptr = (int*)malloc(3 * sizeof(int));if (ptr == nullptr) {std::cout << "Memory allocation failed\n";return 1;}for (int i = 0; i < 3; ++i) {ptr[i] = i + 1;}// 调整内存大小为 5ptr = (int*)realloc(ptr, 5 * sizeof(int));if (ptr == nullptr) {std::cout << "Memory reallocation failed\n";return 1;}for (int i = 3; i < 5; ++i) {ptr[i] = i + 1; // 初始化新分配的部分}for (int i = 0; i < 5; ++i) {std::cout << ptr[i] << " ";}std::cout << "\n";free(ptr);return 0;
}
输出
1 2 3 4 5
4. alloca(Allocate on Stack)
定义
alloca 用于在栈上分配内存,分配的内存在函数返回后会自动释放。
用途
- 用于短期内存分配,避免显式释放。
- 適合临时数据的内存管理。
示例代码
#include <cstdlib>
#include <iostream>int main() {int* ptr = (int*)alloca(5 * sizeof(int)); // 分配 5 个整型大小的内存块在栈上for (int i = 0; i < 5; ++i) {ptr[i] = i + 1;}for (int i = 0; i < 5; ++i) {std::cout << ptr[i] << " ";}std::cout << "\n";// 不需要调用 freereturn 0;
}
输出
1 2 3 4 5
区别分析
| 特性 | malloc | calloc | realloc | alloca |
|---|---|---|---|---|
| 分配位置 | 堆 | 堆 | 堆 | 栈 |
| 是否初始化 | 否 | 是(初始化为 0) | 保持原始数据,扩展部分未初始化 | 否(与 malloc 类似) |
| 内存调整 | 不支持 | 不支持 | 支持 | 不支持 |
| 释放方式 | 手动调用 free | 手动调用 free | 手动调用 free | 自动释放 |
malloc、free
用于分配、释放内存
malloc、free 使用
申请内存,确认是否申请成功
char *str = (char*) malloc(100);
assert(str != nullptr);
释放内存后指针置空
free(p);
p = nullptr;
new、delete
- new / new[]:完成两件事,先底层调用 malloc 分配了内存,然后调用构造函数(创建对象)。
- delete/delete[]:也完成两件事,先调用析构函数(清理资源),然后底层调用 free 释放空间。
- new 在申请内存时会自动计算所需字节数,而 malloc 则需我们自己输入申请内存空间的字节数。
new、delete 使用
申请内存,确认是否申请成功
int main()
{T* t = new T(); // 先内存分配 ,再构造函数delete t; // 先析构函数,再内存释放return 0;
}
相关文章:
C++ 内存分配和管理(八股总结)
C是如何做内存管理的(有哪些内存区域)? (1)堆,使用malloc、free动态分配和释放空间,能分配较大的内存; (2)栈,为函数的局部变量分配内存,能分配…...
如何使用 JSONP 实现跨域请求?
以下是使用 JSONP 实现跨域请求的步骤: 实现步骤: 1. 客户端设置 在客户端,你需要创建一个 <script> 标签,并将其 src 属性设置为跨域请求的 URL,并添加一个 callback 参数。这个 callback 参数将包含一个函数…...
【机器学习实战入门】基于深度学习的乳腺癌分类
什么是深度学习? 作为对机器学习的一种深入方法,深度学习受到了人类大脑和其生物神经网络的启发。它包括深层神经网络、递归神经网络、卷积神经网络和深度信念网络等架构,这些架构由多层组成,数据必须通过这些层才能最终产生输出。…...
Flowable 管理各业务流程:流程设计器 (获取流程模型 XML)、流程部署、启动流程、流程审批、流程挂起和激活、任务分配
文章目录 引言I 表结构主要表前缀及其用途核心表II 流程设计器(Flowable BPMN模型编辑器插件)Flowable-UIvue插件III 流程部署部署步骤例子:根据流程模型ID部署IV 启动流程启动步骤ACT_RE_PROCDEF:流程定义相关信息例子:根据流程 ID 启动流程V 流程审批审批步骤Flowable 审…...
Kafka 日志存储 — 日志索引
每个日志分段文件对应两个索引文件:偏移量索引文件用来建立消息偏移量到物理地址之间的映射;时间戳索引文件根据指定的时间戳来查找对应的偏移量信息。 1 日志索引 Kafka的索引文件以稀疏索引的方式构造消息的索引。它并不保证每个消息在索引文件中都有…...
【大模型】ChatGPT 高效处理图片技巧使用详解
目录 一、前言 二、ChatGPT 4 图片处理介绍 2.1 ChatGPT 4 图片处理概述 2.1.1 图像识别与分类 2.1.2 图像搜索 2.1.3 图像生成 2.1.4 多模态理解 2.1.5 细粒度图像识别 2.1.6 生成式图像任务处理 2.1.7 图像与文本互动 2.2 ChatGPT 4 图片处理应用场景 三、文生图操…...
OceanBase 社区年度之星专访:北控水务纪晓东,社区铁杆开发者
编者按:作为开源数据库,社区的发展和持续进步,来自于每一位贡献者的智慧与支持。2024年度,OceanBase社区特别设立了“年度之星”奖,以表彰和感谢在过去一年中,为社区发展作出突出贡献的朋友。 今日&#x…...
Docker 实现MySQL 主从复制
一、拉取镜像 docker pull mysql:5.7相关命令: 查看镜像:docker images 二、启动镜像 启动mysql01、02容器: docker run -d -p 3310:3306 -v /root/mysql/node-1/config:/etc/mysql/ -v /root/mysql/node-1/data:/var/lib/mysql -e MYS…...
农业农村大数据应用场景|珈和科技“数字乡村一张图”解决方案
近年来,珈和科技持续深耕农业领域,聚焦时空数据服务智慧农业。 珈和利用遥感大数据、云计算、移动互联网、物联网、人工智能等先进技术,搭建“天空地一体化”监测体系,并创新建设了150的全球领先算法模型,广泛应用于高…...
doris 2.1 Queries Acceleration-Hints 学习笔记
1 Hint Classification 1.1 Leading Hint:Specifies the join order according to the order provided in the leading hint. 1.2 Ordered Hint:A specific type of leading hint that specifies the join order as the original text sequence. 1.3 Distribute Hint:Speci…...
STM32 FreeRTOS 任务挂起和恢复---实验
实验目标 学会vTaskSuspend( )、vTaskResume( ) 任务挂起与恢复相关API函数使用: start_task:用来创建其他的三个任务。 task1:实现LED1每500ms闪烁一次。 task2:实现LED2每500ms闪烁一次。 task3:判断按键按下逻辑,KE…...
Ubuntu 24.04 LTS 通过 docker desktop 安装 seafile 搭建个人网盘
准备 Ubuntu 24.04 LTSUbuntu 空闲硬盘挂载Ubuntu 安装 Docker Desktop [我的Ubuntu服务器折腾集](https://blog.csdn.net/jh1513/article/details/145222679。 安装 seafile 参考资料 Docker安装 Seafile OnlyOffice 并配置OnlyOffice到Seafile,实现在线编辑…...
Open3D 最小二乘拟合平面(直接求解法)【2025最新版】
目录 一、算法原理二、代码实现三、结果展示本文由CSDN点云侠原创,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫与GPT。 博客长期更新,本文最近更新时间为:2025年1月18日。 一、算法原理 平面方程的一般表达式为:...
【CC2640R2F】香瓜CC2640R2F之SPI读写W25Q80
本文最后修改时间:2022年01月08日 10:45 一、本节简介 本节以simple_peripheral工程为例,介绍如何使用SPI读写W25Q80(外部flash)。 二、实验平台 1)CC2640R2F平台 ①协议栈版本:CC2640R2 SDK v1.40.00.4…...
探秘Shortest与Stagehand:开启高效测试与自动化新篇
探秘Shortest与Stagehand:开启高效测试与自动化新篇 在数字化浪潮的推动下,网页自动化工具如同繁星般涌现,为众多行业带来了效率的变革。在这些工具中,Shortest和Stagehand凭借其出色的表现,成为了众多开发者、测试人…...
llama 3 笔记
0.简介 llama 3 是在 15 万亿个 Token 上预训练的语言模型,具有 8B 和 70B 两种参数规模,可以支持广泛的用户场景,在各种行业基准上取得了最先进的性能,并提供了一些新功能,包括改进的推理能力。 1.改进亮点 参数规模与模型架构:Llama 3提供了8B和70B两种参数规模的模…...
写作利器:如何用 PicGo + GitHub 图床提高创作效率
你好呀,欢迎来到 Dong雨 的技术小栈 🌱 在这里,我们一同探索代码的奥秘,感受技术的魅力 ✨。 👉 我的小世界:Dong雨 📌 分享我的学习旅程 🛠️ 提供贴心的实用工具 💡 记…...
【文件篇】11.磁盘文件系统
上一篇博客中我们介绍到如果我们要访问文件首先需要打开这个文件,而文件是在磁盘上存储的,也就是说需要在磁盘上找到这个文件的路径。但是磁盘上有很多文件,这些文件都有自己的路径的,这些文件还有内容和属性,它们都是…...
嵌入式产品级-超小尺寸热成像相机(从0到1 硬件-软件-外壳)
Thermal_Imaging_Camera This is a small thermal imaging camera that includes everything from hardware and software. 小尺寸热成像相机-Pico-LVGL-RTOS 基于RP2040 Pico主控与RTOS,榨干双核性能实现LVGL和成图任务并行。ST7789驱动240280屏,CST8…...
三维扫描赋能文化:蔡司3D扫描仪让木质文化遗产焕发新生-沪敖3D
挪威文化历史博物馆在其修复工作中融入现代3D扫描技术,让数百年的历史焕发新生。 文化历史博物馆的工作 文化历史博物馆是奥斯陆大学的一个院系。凭借其在文化历史管理、研究和传播方面的丰富专业知识,该博物馆被誉为挪威博物馆研究领域的领先机构。馆…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...
盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...
【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...
以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...
【生成模型】视频生成论文调研
工作清单 上游应用方向:控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...
Linux 中如何提取压缩文件 ?
Linux 是一种流行的开源操作系统,它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间,使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的,要在 …...
DingDing机器人群消息推送
文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人,点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置,详见说明文档 成功后,记录Webhook 2 API文档说明 点击设置说明 查看自…...
并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...
