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

C++内存管理(区别C语言)深度对比

欢迎来到我的Blog,点击关注哦💕

前言

前面已经介绍了类和对象,对C++面向对象编程已经有了全面认识,接下来要学习对语言学习比较重要的是对内存的管理。

一、内存的分区

  1. 代码区:存放程序的机器指令,通常是可共享的,并且通常为只读的,以防止程序意外修改自身的代码。
  2. 全局/静态存储区:存放全局变量和静态变量,这些变量在程序的整个生命周期内都存在。
  3. 堆区:用于动态分配内存,程序运行时根据需要通过malloc、calloc、realloc等函数在堆区中分配内存空间。
  4. 栈区:存放函数的局部变量和函数调用的参数,由编译器自动管理,遵循后进先出的原则。
  5. 常量区:存放常量数据,如字符串字面量,这些数据在程序运行期间不可修改。
  6. 代码区:存放程序的二进制代码,是程序执行指令的存储空间。

在这里插入图片描述

二、C语言中的内存管理(参考)

  • malloc函数用于动态分配指定大小的内存空间,并返回指向该内存的指针。如果分配成功,返回非NULL指针;否则返回NULL。
  • calloc函数除了分配内存外,还会将分配的内存初始化为零。
  • realloc函数用于调整已分配内存的大小,可能会移动内存块以适应新的大小要求。
  • free函数用于释放之前通过动态内存分配函数分配的内存空间

三、C++中的内存管理

C++内存分配

不同于C语言,C++有着自己独立动态内存开辟的方法:

​ 主要通过newdelete操作符来实现new操作符用于分配单个对象或数组,而deletedelete[]分别用于释放这些对象或数组所占用的内存.

下面是new和delete应用的实例:

 //动态申请一个int大小空间
int* p0 = new int;
//动态申请一个int大小空间并且初始化为0
int* p1 = new int (0);
//动态申请10个int大小空间
int* p2 = new int[10];
//动态申请10个int大小空间并且初始化为0
int* p3 = new int[10] {0};delete p0;
delete p1;
delete[] p2;
delete[] p3; 

注意

  1. 不要使用delete释放非new开辟的空间
  2. 不要使用delete释放同一块空间两次
  3. 如果使用new [ ] 开辟数组进行内存分配,应该使用delete [ ] 来释放
  4. 如果new对一个实体进行内存分配,应该使用delete(没有方括号)进行释放

四、new 和 delete深度探索

有关operator new 和operator delete

operator new

  • operator new是一个特殊的操作符,用于动态分配内存。它与new操作符密切相关,但它们在语义上有所区分。

  • new操作符是一个高级操作符,它不仅分配内存,还自动调用对象的构造函数。

  • operator new仅负责分配内存,不涉及对象的构造。

  • operator new可以被重载,以便为特定的类或全局范围提供自定义的内存分配策略

  • operator new:该函数实际通过``malloc来申请空间,当malloc`申请空间成功时直接返回

  • 申请空间失败, 尝试执行空 间不足应对措施,如果改应对措施用户设置了,则继续申请,否则抛异常。

通俗的讲 ,new 不仅仅可以进行空间开辟,针对自定义类型会调用其构造函数,而new也是调用重载(operator new),进行内存的分配,然而 operator new 进行内存分配是通过malloc进行实现的,这正是区别于C语言的其中一点。

关于时间类和汇编语言:

class Date
{
public:Date(int year = 1,int month = 1,int day = 1):_year(year),_month(month),_day(day){}~Date(){_year = 0;_month = 0;_day = 0;}private:int _year = 1;int _month = 1;int _day = 1;
};Date* d1 = new Date;
00007FF62A0D19FC  mov         ecx,0Ch  
00007FF62A0D1A01  call        operator new (07FF62A0D103Ch)//调用operator new内存分配
00007FF62A0D1A06  mov         qword ptr [rbp+108h],rax  
00007FF62A0D1A0D  cmp         qword ptr [rbp+108h],0  
00007FF62A0D1A15  je          main+5Dh (07FF62A0D1A3Dh)  
00007FF62A0D1A17  mov         r9d,1  
00007FF62A0D1A1D  mov         r8d,1  
00007FF62A0D1A23  mov         edx,1  
00007FF62A0D1A28  mov         rcx,qword ptr [rbp+108h]  
00007FF62A0D1A2F  call        Date::Date (07FF62A0D13D4h)    // 调用构造函数
00007FF62A0D1A34  mov         qword ptr [rbp+118h],rax  
00007FF62A0D1A3B  jmp         main+68h (07FF62A0D1A48h)  
00007FF62A0D1A3D  mov         qword ptr [rbp+118h],0  
00007FF62A0D1A48  mov         rax,qword ptr [rbp+118h]  
00007FF62A0D1A4F  mov         qword ptr [rbp+0E8h],rax  
00007FF62A0D1A56  mov         rax,qword ptr [rbp+0E8h]  
00007FF62A0D1A5D  mov         qword ptr [d1],rax 

operator delete

  • operator delete 是一个全局函数,用于释放之前通过 operator new 分配的内存。
  • 它是 new 操作符的逆运算,负责在内存释放时执行必要的清理工作。
  • operator delete 通常在 delete 表达式中被隐式调用,用于释放单个对象或对象数组的内存
  • 在空间上执行析构函数,完成对象中资源的清理工作
  • 调用operator delete函数释放对象的空间(通过free)
00B72150	push	ebp	已用时间<=1ms	
00B72151	mov	ebp,esp	
00B72153	sub	esp,0cCh	
00B72159	push	ebx	
00B7215A	push	esi	
00B7215B	push	edi	
00B7215C	push	ecx	
00B7215D	lea	edi,[ebp-0Ch]	
00B72160	mov	ecx,3	
00B72165	mov	eax,0cccccccch	
00B7216A	rep stos	dword ptr es:[edi]	
00B7216C	pop	ecx	
00B7216D	mov	dword ptr [this],ecx	
00B72170	mov	ecx,dword ptr [this]	
00B72173	call	A::~A (0B7154Bh)			//调用析构函数
00B72178	mov	eax,dword ptr [ebp+8]	
00B7217B	and	eax,1	
00B7217E	je	__call_empty_init_list_helper<A>+0Eh (0	
00B72180	push	4	
00B72182	mov	eax,dword ptr [t.	ebp	15990024	
00B72185	push	eax	
00B72186	call	operator delete (0B710AAh)	//释放空间
00B7218B	add	esp,8	
00B7218E	mov	eax,dword ptr [this]	
00B72191	pop	edi	
00B72192	pop	esi                                                         

小结

new 和delete 调用的时候内部调用的顺序

  • new 先进行空间的开辟(malloc),在进行对象的实例化
  • delete先进行析构函数的调用,进行资源的销毁,在进行空间的释放(free
new
operatornew
构造函数
delete
析构函数
operatordelete

五、replacement new

在C++中new操作符通常用于在堆上分配内存并调用对象的构造函数。除了常规的new操作符外,C++还提供了operator newplacement new两种替代机制。operator newnew操作符内部使用的函数,可以被重载以提供自定义的内存分配策略。而placement new是一种特殊的new表达式,它允许在已分配的内存上构造对象,而不是分配新的内存。

//用法
new(place_address)type

应用场景:

池化技术:

化技术在C++编程中通常指的是预先分配一定数量的资源(如内存、线程等)并存储在一个“池”中,以便在程序运行时可以快速地从中获取和返回资源,而不是每次都进行昂贵的动态分配和释放操作。

这个就是进行已有空间进行对象实例化

六、C语言和C++内存分配的区别

区别malloc free new delete

  1. mallocfree是函数,而newdelete是操作符
  2. malloc不可以初始化而new可以初始化
  3. malloc进行内存分配的时候是手动计算空间的大小,而new后面跟类型,大小在 [ ]中指定
  4. malloc的返回值为void*, 在使用时必须强转,new不需要,因为new后跟的是空间的类型
  5. malloc申请空间失败是返回NULL,而new申请空间失败是捕获异常
  6. 申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new在申请空间 后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理

void*, 在使用时必须强转,new不需要,因为new后跟的是空间的类型
5. malloc申请空间失败是返回NULL,而new申请空间失败是捕获异常
6. 申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new在申请空间 后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理

相关文章:

C++内存管理(区别C语言)深度对比

欢迎来到我的Blog&#xff0c;点击关注哦&#x1f495; 前言 前面已经介绍了类和对象&#xff0c;对C面向对象编程已经有了全面认识&#xff0c;接下来要学习对语言学习比较重要的是对内存的管理。 一、内存的分区 代码区&#xff1a;存放程序的机器指令&#xff0c;通常是可…...

手把手带你写一个精简版 HashMap 的 put 方法

&#x1f446;&#x1f3fb;&#x1f446;&#x1f3fb;&#x1f446;&#x1f3fb;关注博主&#xff0c;让你的代码变得更加优雅。 前言 HashMap 大家工作中遇到的太多了&#xff0c;已经成了必须使用的类了&#xff0c; 在面试的时候 HashMap 基本是必问题&#xff0c;但是…...

【面试题】数据结构:堆排序的排序思想?

堆排序的排序思想&#xff1f; 堆排序是一种高效的排序算法&#xff0c;其基本思想是利用堆这种数据结构来实现排序。堆是一种特殊的完全二叉树&#xff0c;通常用数组来表示。堆排序的基本步骤如下&#xff1a; 1. 构建初始堆&#xff1a; 将待排序的数组转换成一个最大堆&a…...

PyTorch 深度学习实践-循环神经网络基础篇

视频指路 参考博客笔记 参考笔记二 文章目录 上课笔记基于RNNCell实现总代码 基于RNN实现总代码 含嵌入层的RNN网络嵌入层的作用含嵌入层的RNN网络架构总代码 其他RNN扩展基本注意力机制自注意力机制&#xff08;Self-Attention&#xff09;自注意力计算多头注意力机制&#xf…...

vue实现可拖拽dialog封装

一、实现modal弹窗组件 <template><divv-if"visible"class"customer-dialog"id"customer-dialog":style"dialogStyles"v-dialogDrag:[dialogDrag]><div class"dialog-container"><divclass"dial…...

本地多模态看图说话-llava

其中图片为bast64转码&#xff0c;方便json序列化。 其中模型llava为本地ollama运行的模型&#xff0c;如&#xff1a;ollama run llava 还有其它的模型如&#xff1a;llava-phi3&#xff0c;通过phi3微调过的版本。 实际测试下来&#xff0c;发现本地多模型的性能不佳&…...

人工智能算法工程师(中级)课程14-神经网络的优化与设计之拟合问题及优化与代码详解

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下人工智能算法工程师(中级)课程14-神经网络的优化与设计之拟合问题及优化与代码详解。在机器学习和深度学习领域&#xff0c;模型的训练目标是找到一组参数&#xff0c;使得模型能够从训练数据中学习到有用的模式&am…...

Java异常抛出与处理方法

在Java编程中,异常处理是一个非常重要的部分。通过正确的异常处理,我们可以提高程序的健壮性和可靠性,避免程序在运行过程中出现意外的崩溃。本文将详细讲述Java异常的抛出与处理方法,并通过示例代码进行说明。 一、Java异常的分类 Java中的异常体系结构可以分为三类: 检…...

兼容性测试主要有什么类型?

兼容性测试的类型 有两种类型的兼容性测试。这是一个快速细分。 1、前向兼容性测试 向前兼容性测试或向上兼容性测试可确保当前软件版本在相关组件(例如操作系统、浏览器和第三方库)的未来版本中保持功能。此类测试对于在系统升级期间保持稳定性和用户体验至关重要。 例如&…...

设计模式--组合模式

组合模式&#xff08;Composite Pattern&#xff09;详解 组合模式是一种结构型设计模式&#xff0c;它允许你将对象组合成树形结构来表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。 适用场景 需要表示对象的部分-整体层次结构时&am…...

ArduPilot开源代码之AP_DAL_RangeFinder

ArduPilot开源代码之AP_DAL_RangeFinder 1. 源由2. 框架设计2.1 枚举 Status2.2 公有方法2.3 私有成员变量 3. 重要例程3.1 应用函数3.1.1 ground_clearance_cm_orient3.1.2 max_distance_cm_orient3.1.3 has_orientation3.1.4 get_backend 3.2 其他函数3.2.1 AP_DAL_RangeFind…...

SpringCloud教程 | 第九篇: 使用API Gateway

1、参考资料 SpringCloud基础篇-10-服务网关-Gateway_springcloud gateway-CSDN博客 2、先学习路由&#xff0c;参考了5.1 2.1、建了一个cloudGatewayDemo&#xff0c;这是用来配置网关的工程&#xff0c;配置如下&#xff1a; http://localhost:18080/aaa/name 该接口代码如…...

数据结构——hash(hashmap源码探究)

hash是什么&#xff1f; hash也称为散列&#xff0c;就是把任意长度的输入&#xff0c;通过散列算法&#xff0c;变成固定长度的输出&#xff0c;这个输出值就是散列值。 举例来说明一下什么是hash&#xff1a; 假设我们要把1~12存入到一个大小是5的hash表中&#xff0c;我们…...

国产麒麟、UOS在线打开pdf加盖印章

PageOffice支持两种电子印章方案&#xff0c;可实现对Word、Excel、PDF文档加盖PageOffice自带印章或ZoomSeal电子印章&#xff08;全方位保护、防篡改、防伪造&#xff09;。Word和Excel的盖章功能请参考&#xff1a;Word和Excel加盖印章和签字功能 &#xff08;目前只支持win…...

破解反爬虫策略 /_guard/auto.js(二)实战

这次我们用上篇文章讲到的方法来真正破解一下反爬虫策略&#xff0c;这两个案例是两个不同的网站&#xff0c;一个用的是 /_guard/auto.js&#xff0c;另一个用的是/_guard/delay_jump.js。经过解析发现这两个网站用的反爬虫策略基本是一模一样&#xff0c;只不过在js混淆和生成…...

同样是人工智能 客户在哪儿AI和GPT等大模型有什么不同

书接上回。为了统一回答朋友们的疑惑&#xff0c;此前的两篇文章&#xff0c;着重讲述了客户在哪儿AI的企业全历史行为数据和企业信息查询平台上的数据的区别&#xff0c;以及客户在哪儿AI的ToB获客服务和AI外呼机器人的获客服务的不同。本期接着讲——客户在哪儿AI VS 大模型&…...

AES Android IOS H5 加密方案

前景&#xff1a; 1、本项目原有功能RSA客户端对敏感信息进行加密 2、本次漏洞说是服务端返回值有敏感信息&#xff0c;需要密文返回 3、最初只跟H5联调成功&#xff0c;后续APP联调失败(H5和APP的需求排期不一致)&#xff0c;没关注到通用性 方案&#xff1a; 本次方案不…...

一文了解变阻器和电位器的定义、原理、应用及其对比

变阻器的定义 两端可变电阻器&#xff08;称为变阻器&#xff09;利用电阻来调节电流。电阻丝环绕在陶瓷或瓷器等绝缘芯上。当刮水器沿着电阻丝移动时&#xff0c;电路的有效电阻会发生变化。因此&#xff0c;它提供了精确的电流控制。调光器、电机速度控制器和加热元件使用变…...

WPF实现一个带旋转动画的菜单栏

WPF实现一个带旋转动画的菜单栏 一、创建WPF项目及文件1、创建项目2、创建文件夹及文件3、添加引用 二、代码实现2.ControlAttachProperty类 一、创建WPF项目及文件 1、创建项目 打开VS2022,创建一个WPF项目&#xff0c;如下所示 2、创建文件夹及文件 创建资源文件夹&…...

使用Dockerfile构建镜像

目录 1.使用Dockerfile构建tomcat镜像 1.1 通过ARG传参构建不同版本的tomcat 2.缩小镜像的体积大小 2.1 使用较小体积的基础镜像 2.2 多级构建减少体积 1.使用Dockerfile构建tomcat镜像 cd /opt mkdir tomcat cd tomcat/ 上传tomcat所需的依赖包 使用tar xf 解压三个压缩…...

后进先出(LIFO)详解

LIFO 是 Last In, First Out 的缩写&#xff0c;中文译为后进先出。这是一种数据结构的工作原则&#xff0c;类似于一摞盘子或一叠书本&#xff1a; 最后放进去的元素最先出来 -想象往筒状容器里放盘子&#xff1a; &#xff08;1&#xff09;你放进的最后一个盘子&#xff08…...

MFC内存泄露

1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

Golang dig框架与GraphQL的完美结合

将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用&#xff0c;可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器&#xff0c;能够帮助开发者更好地管理复杂的依赖关系&#xff0c;而 GraphQL 则是一种用于 API 的查询语言&#xff0c;能够提…...

Cinnamon修改面板小工具图标

Cinnamon开始菜单-CSDN博客 设置模块都是做好的&#xff0c;比GNOME简单得多&#xff01; 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验

系列回顾&#xff1a; 在上一篇中&#xff0c;我们成功地为应用集成了数据库&#xff0c;并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了&#xff01;但是&#xff0c;如果你仔细审视那些 API&#xff0c;会发现它们还很“粗糙”&#xff1a;有…...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)

UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中&#xff0c;UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化&#xf…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)

Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败&#xff0c;具体原因是客户端发送了密码认证请求&#xff0c;但Redis服务器未设置密码 1.为Redis设置密码&#xff08;匹配客户端配置&#xff09; 步骤&#xff1a; 1&#xff09;.修…...

Windows安装Miniconda

一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...

Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)

引言 工欲善其事&#xff0c;必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后&#xff0c;我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集&#xff0c;就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...

Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么&#xff1f;它的作用是什么&#xff1f; Spring框架的核心容器是IoC&#xff08;控制反转&#xff09;容器。它的主要作用是管理对…...