C++下的内存管理

文章目录

  • 内存分布
  • C语言中动态内存管理方法
  • C++内存管理
    • new/delete操作内置类型
    • new和delete操作自定义类型
    • operator new 和 operator delete
    • new和delete的实现原理
    • 定位new表达式
  • malloc/free和new/delete的区别
  • 内存泄漏

内存分布

  • :又叫做堆栈–非静态局部变量/函数参数/返回值等,栈是向下增长的
  • 内存映射段:是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可以使用系统接口创建共享内存,做进程间通信。
  • :用于程序运行时内存分配,堆是可以向上增长的。
  • 数据段:存储全局数据和静态数据
  • 代码段:可执行的代码/只读常量

C语言中动态内存管理方法

  • malloc
  • calloc
  • realloc
  • free

C++内存管理

C++除了继承了C语言的动态内存管理方式,还提出了自己的内存管理方式:new和delete。

new/delete操作内置类型


申请和释放单个元素空间

//申请一个int类型的空间,空间大小为4
int* t1 = new int;//申请一个int类型的空间,空间大小为4,初始化为10
int* t2 = new int(10);//销毁一个int类型的单个元素的空间
delete t1;
delete t2;

申请和释放连续元素空间

//申请一个int类型的空间,空间大小为4*10
int* t3 = new int[10];//申请一个int类型的空间,空间大小为4*10,并且进行初始化
//前三个元素空间初始化为1,2,3,后面的全面初始化为0
int* t4 = new int[10]{1,2,3};//销毁连续元素空间
delete t3[];
delete t4[];
  • 申请和释放单个元素的空间,使用new和delete操作符
  • 申请和释放连续的空间,使用new[]和delete[]

new和delete操作自定义类型

  • malloc不方便解决动态申请的自定义类型对象的初始化问题。
calss A
{
public:A(int a = 0): _a(a);{}~A(){}private:int _a;
}

单个空间开辟

int main()
{//创建一个A类型的对象,为这个对象开辟一块空间//malloc 只是开辟了空间A* p1 = (A*)malloc(sizeof(A));//new 在开辟空间的同时进行了调用构造函数,进行了初始化A* p2 = new A(1);free(p1);delete p2;return 0;
}

多个

int main()
{A aa1(1);A aa2(2);A aa3(3);A* p3 = new A[3]{aa1,aa2,aa3};A* p4 = new A[3]{A(1),A(2),A(3)};A* p5 = new A[3]{1,2,3};delete[] p3;delete[] p4;delete[] p5;return 0;
}

总结

  1. new的本质:开空间+调用构造函数初始化

    • 开空间
    • 调用构造函数
      • 存在默认构造调用默认构造,没有默认构造报错,可以显式的调用构造。
  2. delete的本质:调用析构函数+释放空间

    new失败的时候会抛出异常

    内置类型的空间申请和释放,new和malloc除了用法上没有区别,只有在自定义类型上有区别。

异常捕获

try
{}
catch
{}

operator new 和 operator delete

new和delete是用户进行动态内存申请和释放的操作符,operator new和operator delete是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间。

  • operator new:该函数的底层实际上是通过malloc来申请空间,当malloc申请空间成功的时候直接返回,申请空间失败的时候,尝试执行空间不足应对措施,如果该应对措施用户设置了,则继续申请,否则抛出异常。

  • operator delete:该函数是通过free来释放空间的。

  • c语言单纯的malloc和free对异常的处理不符合实际的需求,所以对c语言进行了封装,产生了operator new和operator delete函数。

new和delete的实现原理

内置类型
如果申请的是内置类型的空间,new和malloc、delete和free基本上相似,不同的地方是:new/delete申请和释放的是单个元素的空间,new[]delete[]申请的是连续空间,而且new在申请空间时会抛出异常,malloc会返回null。

自定义类型

  • new的原理

    • 调用operator new函数申请空间
    • 在申请的空间上执行构造函数,完成对象的构造
  • delete的原理

    • 在空间上执行析构函数,完成对象中资源的清理工作
    • 调用operator delete函数释放对象的孔吉纳
  • new[N]的原理

    • 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对象空间的申请
    • 在申请的空间上执行N次构造函数
  • delete[]的原理

    • 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理
    • 调用·operator delete[]释放空间,实际在·operator delete[]中调用operator delete来释放空间

    melloc/freenew/deletenew[]/delete[]一定要配对使用。

  • 构造函数不可以直接显式调用,但是可以通过定位new显式调用

  • 析构函数可以显式调用

定位new表达式

定位new表达式是在已经分配的原始内存空间中调用构造函数初始化一个对象。

格式

n(place_address)type或者new(place_address)type(initializer-list)new(p1)A(10);
place_address必须是一个指针,initalizer-list是类型的初始化列表。

使用场景
定位new表达式在实际中一般是配合内存池使用,因为内存池分配出的内存没有初始化,所以如果是自定义类型的对象,需要使用new的定义表达式进行显式调构造函数进行初始化。

malloc/free和new/delete的区别

malloc/free和new/delete的共同点:都是堆上申请空间,并且需要用户手动释放。不同的地方是:

  • malloc和free是函数,new和delete是操作符。
  • malloc申请的空间不会初始化,new可以初始化。
  • malloc申请空间时,需要手动计算空间大小并且进行传递,new只需要在其后面跟上空间的类型即可。如果存在多个对象,[]中指定对象个数即可。
  • malloc的返回值为void*,在使用时必须强转,new不需要,因为new后跟的是空间的类型。
  • malloc申请空间失败的时候,返程的是NULL,因此使用时必须判空,new不需要,但是new需要捕获异常
  • 申请自定义类型对象的时候,malloc/free之后开辟空间,不会调用构造函数和析构函数。而new在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理。

内存泄漏

概念

  • 内存泄漏:
    内存泄漏是指因为疏忽或者错误做成程序未能释放已经不再使用的内存的清空,内存泄漏并不是指内存在物理上的小时,而是应用程序分配某段内存后,因为设计错误,失去了对该段内存的控制,因而造成了内存的浪费。
  • 内存泄漏的危害
    长期运行的程序出现内存泄露,影响很大,如操作系统、后台服务等,出现内存泄漏会导致响应越来越慢,最终卡死。

分类
C/C++程序中一般关心两种内存泄漏:

  • 堆内存泄漏(Heap leak)
    堆内存指的是程序执行中一句需要分配通过malloc/calloc/realloc/new等从堆中分配的一块内存,用完后必须通过调用相应的free或者delete删掉,假设程序的设计错误导致这部分内存没有被释放,那么以后这部分空间的内存将无法再被使用,就会产生Heap Leak。
  • 系统资源泄漏
    指程序使用系统分配的资源,比如文件描述符、管道等没有使用对应的函数释放掉,导致系统资源的浪费,严重可能导致系统效能减少,系统执行不稳定。

避免内存泄漏

  • 工程前期良好的设计规范、养成良好的编码规范,申请的内存空间记着匹配二点去释放。
  • 使用RAII思想或者智能指针来管理资源。
  • 使用内部实现的私有内存管理库。
  • 使用内存泄漏管理工具检测。

解决方案

  • 事前预防型,如智能指针
  • 事后查错型,泄漏检测工具。

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

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

相关文章

算法学习笔记(5.1)-基于比较的高效排序算法(快速排序,堆排序)

##时间复杂度O(NlogN) 目录 ##时间复杂度O(NlogN) ##快速排序 ##原理 ##图例 ##代码实现 ##堆排序 ##原理 ##图例 ##代码实现 ##快速排序 ##原理 快速排序的核心操作是“哨兵划分”,其目标是:选择数组中的某个元素作为“基准数”,…

【编译原理复习笔记】语法分析(一)

分类 语法分析可以按照分析方向分为两类 自顶向下/自底向上 自顶向下的分析 从分析树的顶部向底部方向构造分析树 每一步推导需要做两个选择: (1)需要替换哪个非终结符 (2)用哪个产生式 最左推导 在最左推导中&am…

【重学C++】02 脱离指针陷阱:深入浅出 C++ 智能指针

前言 大家好,今天是【重学C】系列的第二讲,我们来聊聊C的智能指针。 为什么需要智能指针 在上一讲《01 C如何进行内存资源管理》中,提到了对于堆上的内存资源,需要我们手动分配和释放。管理这些资源是个技术活,一不…

正点原子LWIP学习笔记(一)lwIP入门

lwIP入门 一、lwIP简介(了解)二、lwIP结构框图(了解)三、如何学习lwIP(熟悉) 一、lwIP简介(了解) lwIP是一个小型开源的TCP/IP协议栈 阉割的TCP/IP协议 TCP/IP协议栈结构&#xff0…

C语言游戏实战(12):植物大战僵尸(坤版)

植物大战僵尸 前言: 本游戏使用C语言和easyx图形库编写,通过这个项目我们可以深度的掌握C语言的各种语言特性和高级开发技巧,以及锻炼我们独立的项目开发能力, 在开始编写代码之前,我们需要先了解一下游戏的基本规则…

基础2 JAVA图形编程桌面:探索图形程序的抽象实现

嘿,大家好!我非常高兴又一次有机会与大家相聚,分享新的知识和经验。对于热爱编程和探索新技术的朋友们来说,今天的内容绝对不容错过。我为大家准备了一个详尽的视频教程:《基础2 JAVA 图形编程:主程序调用…

git拉取项目前需要操作哪些?

1.输入 $ ssh-keygen -t rsa -C "秘钥说明" 按enter键 2.出现 ssh/id_rsa:(输入也可以不输入也可以) 然后按enter键 3.出现empty for no passphrase:(输入也可以不输入也可以) 然后按enter键 4.出现same passphrase again: (输入也可以不输入也…

20240516-Flyme AIOS 特种兵发布会

目录 1 Flyme AIOS 2 路演功能 2.1 拖拽流转 2.2 任务剧本自定义 2.3 智能体商店 2.4 实况通知 2.5 AI壁纸 3 MYVU 3.1 翻译功能 3.2 AR导航-骑行 3.3 AI语音转文字-科技向善 3.4 Flyme AR-提词器增强 1 Flyme AIOS 1)目标:All in AI&#…

AI绘图Stable Diffusion,如何无损高清放大图片,保姆级教程建议收藏!

前言 我们在用 stable diffusion 制作AI图片时,默认生成图片的尺寸为512*512,即使是竖图一般也就是512*768,如果再把尺寸设置大一些,就会因为硬件算力不够而造成系统崩溃,今天就来跟大家聊一聊,如何将制作…

RocketMQ-Dashboard 控制台使用详解

1 安装部署 具体部署启动请参考:RocketMQ从安装、压测到运维一站式文档_rocketmq benchmark压测-CSDN博客 RocketMq的dashboard,有运维页面,驾驶舱,集群页面,主题页面,消费者页面,生产者页面&…

【Kubenetes】边缘计算KubeEdge架构设计详解

文章目录 前言KubeEdge云边通信方式云端架构设计EdgeController:云到边:边到云 DeviceController:云到边边到云 边缘端架构设计EdgedPod的管理部分Pod的监控部分Pod的卷管理Pod的垃圾回收Pod同步管理 MetaMangger从云到边缘的更新 (Update From Cloud To Edge)从边缘…

Covalent长期数据设施,支持基于 “blob” 、总锁仓54亿美元的L2

Covalent Network(CQT)是领先的历史数据可用性网络,通过其在 Web3 中超过 225 个区块链上的结构化数据基础设施,为数千名客户和开发人员提供支持。Covalent Network(CQT)正在与未来以太坊的进步需求相匹配&…

SQL慢查询学习篇

https://www.cnblogs.com/isyues/p/17733015.html 1. 对扫到的SQL慢查询语句执行 explain explain select task_id, channel, count(task_id) as count from tablename where send_time > "2024-05-10 16:13:59" and send_time < "2024-05-14 16:13:59…

api接口、api文档、api调试、api测试

应用程序接口是一组定义、程序及协议的集合&#xff0c;通过 API 接口实现计算机软件之间的相互通信。API 的一个主要功能是提供通用功能集。程序员通过调用 API 函数对应用程序进行开发&#xff0c;可以减轻编程任务。 API 同时也是一种中间件&#xff0c;为各种不同平台提供数…

展馆展厅设计施工流程

1、需求分析和确定&#xff1a; 与客户沟通&#xff0c;了解客户需求&#xff0c;对展馆展厅的用途、面积、功能、展品特点等进行分析&#xff0c;并确定设计方案。 2、方案设计 根据需求确定设计方案&#xff0c;包括平面布局、展品陈列、展示方式、照明等。设计师需要提供设计…

如何在Spring启动的时候执行一些操作

如何在Spring启动的时候执行一些操作 在Spring启动的时候执行一些操作有多种方式。你可以通过实现ApplicationRunner或者CommandLineRunner接口&#xff0c;在Spring Boot应用程序启动后执行特定操作。另外&#xff0c;你也可以使用PostConstruct注解&#xff0c;在Spring Bea…

【考研数学】张宇《1000题》强化阶段正确率多少算合格?

张宇1000题真的很练人心态.... 基础不好&#xff0c;建议别碰1000题 基础好&#xff0c;1000题建议在两个月以内刷完 如果自己本身在基础阶段学的比较水&#xff0c;自己的薄弱点刷了一小部分题没有针对性完全解决&#xff0c;转身去刷1000题就会发现&#xff0c;会的题目刷…

shell脚本-重定向与管道符

一、重定向 因为shell脚本有着批量操作的特殊性&#xff0c;大部分操作处于后台执行&#xff0c;不需要用户进行干预&#xff0c;所以提取、过滤并执行信息十分需要重定向和管道。重定向的意思是不输出到默认设备上&#xff0c;而是输出到你指定的位置&#xff08;文件、其他输…

1.微信小程序开发之准备工作

1.微信小程序账号注册 小程序开发 与 网页开发不一样&#xff0c;在开始微信小程序开发之前&#xff0c;需要访问 微信公众平台&#xff0c;注册一个微信小程序账号。 在拥有了小程序的账号以后&#xff0c;我们才可以开发和管理小程序&#xff0c;后续可以通过该账号进行开发…

国网电力分公司、税务企业如何向央媒投稿?

税务、电力、银行等单位如果想要将稿件发布到中央媒体&#xff0c;可以遵循为大家整理的以下步骤和建议&#xff1a; 了解央媒的定位与要求&#xff1a;中央媒体&#xff0c;如新华社、人民日报、中央电视台等&#xff0c;都有其独特的报道风格和关注重点。在投稿前&#xff0…