C++动态内存管理:与C语言动态内存管理的差异之争

当你改错一行代码的时候:

当你想要重构别人的代码时:

目录

前言

一、C/C++的内存分布

二、C/C++语言中的动态内存管理

 三、new与delete的实现原理

总结:

 


前言

在C++中,内存管理是一个至关重要的主题。正确地管理内存可以避免内存泄漏和内存访问错误等问题,提高程序的性能和可靠性。本文将深入探讨C++中的内存管理机制,包括从C语言内存管理到C++内存管理转变,二者的关联等内容。

一、C/C++的内存分布

C/C++程序内存主要使用了以下几个区域,让我们先来认识一下:

1、内核区域:

“内核区域”通常指的是操作系统的核心部分,它是操作系统的基本组成部分之一。内核负责管理计算机的硬件资源,并提供给应用程序访问这些资源的接口。但是我们用户的代码读写不了它,所以这里也不主要讲解。

2、栈区:

栈区是计算机内存中的一部分,用于存储函数调用时的局部变量、函数参数、函数返回地址等临时数据。栈是一种后进先出(LIFO)的数据结构,因此栈区也被称为后进先出(LIFO)内存区域。

在典型的程序执行过程中,每当一个函数被调用时,该函数的局部变量和参数被分配到栈区,并且该函数的返回地址被推入栈中。当函数执行完成后,栈中的这些数据被销毁,栈的指针回退到上一个函数的栈帧。这种方式使得程序能够有效地管理函数调用和返回。

栈区的大小通常是固定的,由操作系统在程序启动时分配。如果栈区的空间被耗尽,就会发生栈溢出(stack overflow)错误,这通常是由于递归函数调用层数过多或者局部变量占用过多栈空间所导致的。

3、内存映射段:

存映射段(Memory-mapped segment)是指操作系统中的一种机制,它允许将文件或其他设备映射到进程的地址空间,使得这些文件或设备能够像内存一样被访问和操作。(我们这里也不讲解,只是单纯提一下)

4、堆区:

堆区是计算机内存中的一部分,用于动态分配内存空间。在堆区中,程序员可以通过调用诸如 malloc()、calloc() 或 new 等函数来请求内存空间,用于存储程序中动态创建的数据结构,比如链表、树、对象等。(也就是我们今天所要讲解的动态内存管理所涉及的区域)

5、数据段:

数据段(Data Segment)是指存储程序中已声明的全局变量和静态变量的内存区域。数据段通常位于进程的虚拟地址空间中的一个固定位置,并且在程序加载时被分配。(全局变量与static修饰的变量)

(静态变量主要有三种方式:

1、在函数内部使用 static 关键字声明

2、在全局作用域内使用 static 关键字声明

3、在函数内部不使用 static 关键字,但函数外部使用 static 修饰该函数

6、代码段:

代码段中通常存储着可执行的程序与只读常量如我们规定的“a,n,f,j”等字符

二、C/C++语言中的动态内存管理

1、C语言:

在C语言中,我们通常使用malloc/calloc/realloc/free四个关键字来管理我们的动态内存分配。

malloc()函数:

  • void *malloc(size_t size);
  • 用于动态分配指定大小的内存块。
  • 返回一个指向分配的内存块的指针,或者在分配失败时返回 NULL。

calloc()函数 :

  • void *calloc(size_t num, size_t size);
  • 用于动态分配指定数量和大小的内存块,并将其初始化为零。
  • 返回一个指向分配的内存块的指针,或者在分配失败时返回 NULL。

realloc()函数;

  • void *realloc(void *ptr, size_t size);
  • 用于更改之前分配的内存块的大小。
  • 返回一个指向重新分配的内存块的指针,或者在分配失败时返回 NULL。

 free()函数:

  • void free(void *ptr);
  • 用于释放之前分配的内存块。

 在C语言中,malloc()等函数会返回 void* 类型的指针,需要强制类型转换为目标类型,这使得使用十分不方便。而C++内存管理只需要用new与delete两个运算符就可以做得更加高级,更加安全便捷。

2、C++:
C++中用 newdelete 运算符来动态地分配和释放内存。

new运算符:

  • new 运算符用于动态分配内存空间,并返回所分配内存的地址。
  • new 运算符的基本语法为:new 数据类型new 数据类型[数组大小]
  • 动态分配的内存必须由程序员显式地释放,否则会造成内存泄漏。

delete运算符:

  • delete 运算符用于释放动态分配的内存空间。
  • delete 运算符的基本语法为:delete 指针变量delete[] 指针变量(释放数组)。
  • 动态分配的内存在不再使用时必须由程序员显式地释放,否则会造成内存泄漏。

 (其实在C++11中还新增了智能指针的概念,但现在我们先不提及)

int main()
{int* arr = new int[10];// 分配一个包含10个整数的内存块int* ptr = new int; // 动态分配一个整数的内存空间int* ptr2 = new int(10); // 动态分配一个整数的内存空间并且初始化为10delete ptr;delete ptr2;//释放内存delete[] arr;//加上[]表示多个数据return 0;
}

//分配自定义类型class A
{
public:A(int a = 0):_a(a){cout << "A():" << endl;}~A(){cout << "~A():" << endl;}
private:int _a;};int main()
{A* ptr1 = new A;A* ptr2 = (A*)malloc(sizeof(A));delete ptr1;free(ptr2);return 0;
}
结果可以发现,我们在new与delete的时候会自动调用自定义类型的构造与析构函数,而C的malloc与free则不会。
new delete 是用户进行 动态内存申请和释放的操作符 operator new operator delete
系统提供的 全局函数 new 在底层调用 operator new 全局函数来申请空间, delete 在底层通过
operator delete 全局函数来释放空间。

实际上,operator new 实际也是通过malloc来申请空间,如果malloc申请空间成功就直接返回,否则执行用户提供的空间不足应对措施,如果用户提供该措施就继续申请,否则就抛异常。(以后讲解异常概念)operator delete 最终是通过free来释放空间的

 三、new与delete的实现原理

1、对于内置类型来说:

new与malloc,delete与free基本类似,不同的地方是:

new与delete申请与释放的是单个元素的空间,new[]与delete[]申请与释放的是连续的空间,而且new在申请失败时会抛出异常,malloc则会直接返回NULL。

2、对于自定义类型来说:

new的原理:

1. 调用 operator new 函数申请空间
2. 在申请的空间上执行构造函数,完成对象的构造
delete的原理
 
1. 在空间上执行析构函数,完成对象中资源的清理工作
2. 调用 operator delete 函数释放对象的空间
new T[N] 的原理:
1. 调用 operator new[] 函数,在 operator new[] 中实际调用 operator new 函数完成 N 个对
象空间的申请
2. 在申请的空间上执行 N 次构造函数
delete[] 的原理
1. 在释放的对象空间上执行 N 次析构函数,完成 N 个对象中资源的清理
2. 调用 operator delete[] 释放空间,实际在 operator delete[] 中调用 operator delete 来释
放空间

总结:

malloc/free new/delete 的共同点是:都是从堆上申请空间,并且需要用户手动释放。不同的地
方是:
1. mallocfree是函数,newdelete是操作符
2. malloc申请的空间不会初始化,new可以初始化
3. malloc申请空间时,需要手动计算空间大小并传递,new只需在其后跟上空间的类型即可,
如果是多个对象,[]中指定对象个数即可
4. malloc的返回值为void*, 在使用时必须强转,new不需要,因为new后跟的是空间的类型
5. malloc申请空间失败时,返回的是NULL,因此使用时必须判空,new不需要,但是new
要捕获异常
6. 申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new
在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成
空间中资源的清理

 

希望通过本篇文章,能够对你区分C++与C语言内存管理有所帮助。

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

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

相关文章

TriCore: Architecture

说明 本文是 英飞凌 架构文档 TriCore TC162P core archiecture Volume 1 of 2 (infineon.com) 的笔记&#xff0c;稍作整理方便查阅&#xff0c;错误之处&#xff0c;还请指正&#xff0c;谢谢 :) 1. Architecture 2. General Purpose & System Register 名词列表&#…

佛山市举办2024年护士节庆祝活动

“作为一名在护理岗位上工作了39年的护士,能够在退休前参加这样温情的护士节活动,获得一个纪念胸章和一份荣誉证书,让我很感动!”第七届“南粤好护士”、佛山市第一人民医院急诊科护士长罗银秋说道。5月10日下午,由佛山市卫生健康局主办、佛山市护理学会协办、佛山市第一人民医…

KIE关键信息抽取——SDMG-R

https://arxiv.org/pdf/2103.14470https://arxiv.org/pdf/2103.14470 1.概述 背景:传统的关键信息提取方法依赖于模板匹配,这使它们难以泛化到未见过的模板,且对文本识别错误不够鲁棒。SDMG-R方法:提出一种端到端的双模态图推理方法,通过构建双模态图(视觉和文本特征),…

Python远程连接Linux执行操作

一、任务要求 要使用Python编写代码来远程给Linux主机上传一个文件&#xff0c;可以使用paramiko库&#xff0c;这是一个实现了SSHv2协议的Python库&#xff0c;它支持SSH连接&#xff08;包括客户端和服务端&#xff09;&#xff0c;并且提供SFTP&#xff08;SSH File Transf…

Vision Mamba:高效视觉表示学习双向状态空间模型,超越Vision Transformer!

DeepVisionary 每日深度学习前沿科技推送&顶会论文分享&#xff0c;与你一起了解前沿深度学习信息&#xff01; Vision Mamba: Efficient Visual Representation Learning with Bidirectional State Space Model 引言&#xff1a;探索视觉领域的新方向 在计算机视觉领域&…

地球行星UE5和UE4

地球行星&#xff0c;包含多种地球风格&#xff0c;可蓝图控制自转和停止&#xff0c;可材质自转. 支持版本4.21-5.4版本 下载位置&#xff1a;https://mbd.pub/o/bread/ZpWZm5lv b站工坊&#xff1a;https://gf.bilibili.com/item/detail/1105582041 _______________________…

luceda ipkiss教程 68:通过代码模板提高线路设计效率

在用ipkiss设计器件或者线路时&#xff0c;经常需要输入: from ipkiss3 import all as i3那么有什么办法可以快速输入这段代码呢&#xff1f;这里就可以利用Pycharm的 live template功能&#xff0c;只需要将文件&#xff1a;ipkiss.xml &#xff08;luceda ipkiss教程 68&…

Vue3:项目创建

Vue 3 相对于 Vue 2 带来了许多改进和优点&#xff0c;这些改进主要是为了提高性能、开发体验和可维护性。但是对于创建项目&#xff0c;Vue3也可以采用跟Vue2相同的方式。 使用CLI创建 1. 安装Vue CLI 首先&#xff0c;确保你已经安装了Node.js&#xff08;建议使用LTS版本…

金蝶向左,用友向右

【科技明说 &#xff5c; 科技热点关注】 科技明说分析指出&#xff0c;金蝶和用友作为国内数一数二的财务软件巨头&#xff0c;两者不仅是竞争对手&#xff0c;也是很好的发展队友&#xff0c;在云计算时代、AI时代都相继进行了不同程度的产品与服务创新。与时俱进的好处&…

如何将图片表格转成excel?分享3种好用的软件!

在信息爆炸的时代&#xff0c;我们每天都会接触到大量的图片表格。这些表格中可能包含着我们需要的各种数据和信息&#xff0c;但是如何将它们快速、准确地转化为Excel格式&#xff0c;以便我们进行编辑、分析呢&#xff1f;今天&#xff0c;就让我们一起来探讨一下如何将图片表…

图形网络的自适应扩散 笔记

1 Title Adaptive Diffusion in Graph Neural Networks&#xff08;Jialin Zhao、Yuxiao Dong、Ming Ding、Evgeny Kharlamov、Jie Tang&#xff09;【NIPS 2021】 2 Conclusion The neighborhood size in GDC is manually tuned for each graph by conductin…

AXI4写时序在AXI Block RAM (BRAM) IP核中的应用

在本文中将展示描述了AXI从设备&#xff08;slave&#xff09;AXI BRAM Controller IP核与Xilinx AXI Interconnect之间的写时序关系。 1 Single Write 图1是一个关于32位宽度的BRAM&#xff08;Block RAM&#xff09;的单次写入操作的例子。这个例子展示了如何向地址0x1000h…

MySQL——变量的浮点数问题处理

新建链接&#xff0c;自带world数据库&#xff0c;里面自带city表格。 DQL #MySQL变量的浮点数问题处理 set dx3.14,dy3.25; select dxdy;#计算显示异常&#xff0c;会有很多00000的提示set resultdxdy; select result; 查询结果

C++青少年简明教程:C++中的常量、变量、表达式和语句

C青少年简明教程&#xff1a;C中的常量、变量、表达式和语句 在C编程中&#xff0c;常量、变量、表达式和语句是基本的编程概念。 常量&#xff08;Constants&#xff09;&#xff1a;在程序中具有固定值的数据称为常量。常量可以是字面值&#xff0c;如整数、浮点数、字符或…

【挑战30天首通《谷粒商城》】-【第一天】【10 番外篇】 解决docker 仓库无法访问 + MobaXterm连接VirtualBox虚拟机

文章目录 课程介绍 1、解决docker 仓库无法访问 2、 MobaXterm连接VirtualBox虚拟机 Stage 1&#xff1a;下载MobaXterm选择适合你的版本 Stage 2&#xff1a;vagrant ssh 连接&#xff0c;开启ssh访问 Stage 2-1&#xff1a;su获取root账号权限,输入密码&#xff08;默认vagra…

【Web】CTFSHOW 七夕杯 题解

目录 web签到 easy_calc easy_cmd web签到 CTF中字符长度限制下的命令执行 rce(7字符5字符4字符)汇总_ctf中字符长度限制下的命令执行 5个字符-CSDN博客7长度限制直接梭了 也可以打临时文件RCE import requestsurl "http://4ae13f1e-8e42-4afa-a6a6-1076acd08211.c…

C++ Builder XE EnumWindowsProc遍历所有窗口的名称

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) { // 这里可以添加你的处理逻辑 // 例如&#xff0c;将句柄添加到列表中或者其他操作 // 这里我们仅仅输出到调试窗口 OutputDebugString(L"枚举窗口句柄: "); char windowHandle[10];…

ICode国际青少年编程竞赛- Python-4级训练场-while语句入门

ICode国际青少年编程竞赛- Python-4级训练场-while语句入门 1、 while Flyer.disappear():wait() Dev.step(2)2、 Dev.step(1) while Flyer.disappear():wait() Dev.step(5)3、 while Flyer[0].disappear():wait() Dev.step(3) Dev.step(-1) while Flyer[0].disappear():…

准实时数仓搭建指南:以仓储式会员商超为模拟场景

在电商和新零售持续冲击传统零售商超的今天&#xff0c;仓储式会员店反而成功逃脱曾经的“水土不服”预测&#xff0c;业绩一路向好。与此同时&#xff0c;随着人工智能、大数据、智慧物流等技术的不断革新&#xff0c;零售批发的消费场景也进一步拓展&#xff0c;对数据分析的…

RERCS系统-WDA+BOPF框架实战例子 PART 1-新建List UIBB(列表组件)并分配Feeder Class和Node Element

需求背景&#xff1a; 已有的项目主数据功能&#xff0c;新增一个列表UIBB显示主数据额外的关联数据明细。 1、Fiori页面通过右键-技术帮助打开对应的组件配置&#xff1b; 2、双击对应的组件配置&#xff0c;调整对应的页面新建UIBB&#xff1b; 3、填写对应的UIBB属性字段&a…