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思想或者智能指针来管理资源。
  • 使用内部实现的私有内存管理库。
  • 使用内存泄漏管理工具检测。

解决方案

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

org.json下载方法

介绍org.json下载的一些方法。 工具/原料 浏览器 方式一 在百度上搜索org.json,点击第一个搜索结果。进入JSON网站后,可以看到有各种语言版本的json工具包,选择JSON-java。 点击JSON-java后页面跳转到GitHub上,在该网页上点击…

C++设计模式---面向对象原则

面向对象设计原则 原则的目的:高内聚,低耦合 1. 单一职责原则 类的职责单一,对外只提供一种功能,而引起类变化的原因都应该只有一个。 2. 开闭原则 对扩展开放,对修改关闭;增加功能是通过增加代码来实现的&…

webpack5零基础入门-15样式兼容性问题处理

1.下载相关依赖 npm i postcss-loader postcss postcss-preset-env -D 2.在webpack.config.js中配置 注意:postcss-loader要在css-loader后面配置 3.写一个flex布局,flex是存在一定的兼容性问题的 4.打包 可以看到打包后未被处理 1.下载相关依赖 np…

js实现鼠标拖拽多选功能

实现功能 在PC端的H5页面中&#xff0c;客户拖动鼠标可以连选多个选项 效果展示 具体代码如下 <!DOCTYPE html> <html><head><title>鼠标拖拽多选功能</title><script src"https://cdn.bootcss.com/jquery/1.10.2/jquery.min.js&quo…

【Text2SQL 经典模型】TypeSQL

论文&#xff1a;TypeSQL: Knowledge-Based Type-Aware Neural Text-to-SQL Generation ⭐⭐⭐ Code: TypeSQL | GitHub 一、论文速读 本论文是在 SQLNet 网络上做的改进&#xff0c;其思路也是先预先构建一个 SQL sketch&#xff0c;然后再填充 slots 从而生成 SQL。 论文发…

Epson推出多摄像头接口芯片S2D13P04

目前&#xff0c;汽车电子的发展日新月异&#xff0c;汽车显示控制器也更多地采用芯片集成化设计的趋势伴随着目前ADAS系统的发展&#xff0c;大量的摄像头和雷达传感器应用到汽车电子中。传统的系统集成方案通常采用多通道电路来处理多摄像头信号输入的方案&#xff0c;但是车…

Oracle体系结构初探:数据库启动与停止

往期内容 参数管理 控制文件添加 启动 在启动Oracle数据库时&#xff0c;我们一般会使用如下命令&#xff1a; startup 虽然命令只有一个&#xff0c;但其中却是经历了3个阶段&#xff0c;从下面执行 startup 命令返回也可以看出来。 总结为3个阶段&#xff1a; nomount&…

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-22讲 RTC 时钟设置

前言&#xff1a; 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM&#xff08;MX6U&#xff09;裸机篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…

GPT‑4o普通账户也可以免费用

网址 https://chatgpt.com/ 试了一下&#xff0c;免费的确实显示GPT‑4o的模型&#xff0c;问了一下可以联网&#xff0c;不知道能不能通过插件出图 有兴趣的可以试试

测试环境KDE组件漏洞修复

yarn白名单方案 解决漏洞: 方案: 此方式主要使用iptables的功能,对yarn的resourceManager服务的8088端口进行访问ip限制,目的限制8088端口只允许集群内ip访问。 #分别在两台resourceManager节点执行以下步骤ssh kde-offline1 #安装iptables服务,并启动设置为开机自启 yum …

【Android】WorkManager(章二)

剩余的三部分 官方文档 案例 实现下载器&#xff0c;并监听下载进度 界面 定义Worker 在官方案例的前提下&#xff0c;进行完善 下载download 下载进度 授予权限 开始工作并监听 完整代码 MainActivity.java package com.test.downloadworkerapplication;import static…

键盘盲打是练出来的

键盘盲打是练出来的&#xff0c;那该如何练习呢&#xff1f;很简单&#xff0c;看着屏幕提示跟着练。屏幕上哪里有提示呢&#xff1f;请看我的截屏&#xff1a; 截屏下方有8个带字母的方块按钮&#xff0c;这个就是提示&#xff0c;也就是我们常说的8个基准键位&#xff0c;我…

Redis学习篇2:Redis在IEDA中的应用

本文继上文开始讲述了Redis在IDEA中如何应用以及集成进入spring开发环境&#xff0c;以及如何使用Redis客户端。上一个文章&#xff1a;Redis学习篇1&#xff1a;初识Redishttps://blog.csdn.net/jialuosi/article/details/139057088 一、Redis在java中的客户端 二、SpringDat…

通联支付API集成(适用于SpringBoot)

目标&#xff1a; 学习如何使用Java与通联支付API进行交互 实现一个简单的支付下单和查询订单状态的示例 所需材料&#xff1a; 通联支付API文档 官方文档https://aipboss.allinpay.com/know/devhelp/main.php?pid38#mid313 通联支付加签代码SybUtil package com.allin…

从GPT-4o和Google I/O看AI技术变革与未来趋势

引言 在科技界的激烈竞争中&#xff0c;OpenAI 和 Google 这两大巨头不断推出新技术&#xff0c;引领着人工智能的发展。最近&#xff0c;OpenAI 发布了 GPT-4o&#xff0c;恰逢 Google I/O 大会前一天&#xff0c;这一发布会似乎有意“截胡” Google I/O。今天&#xff0c;我…

python实现520表白图案

今天是520哦&#xff0c;作为程序员有必要通过自己的专业知识来向你的爱人表达下你的爱意。那么python中怎么实现绘制520表白图案呢&#xff1f;这里给出方法&#xff1a; 1、使用图形库&#xff08;如turtle&#xff09; 使用turtle模块&#xff0c;你可以绘制各种形状和图案…

go 爬虫之 colly 简单示例

1. 背景 colly 是 Go 实现的比较有名的一款爬虫框架&#xff0c;而且 Go 在高并发和分布式场景的优势也正是爬虫技术所需要的。它的主要特点是轻量、快速&#xff0c;设计非常优雅&#xff0c;并且分布式的支持也非常简单&#xff0c;易于扩展。 2. 官方文档 https://go-col…

大模型的实践应用24-LLaMA-Factory微调通义千问qwen1.5-1.8B模型的实例

大家好,我是微学AI,今天给大家介绍一下大模型的实践应用24-LLaMA-Factory微调通义千问qwen1.5-1.8B模型的实例, LLaMA-Factory是一个专门用于大语言模型微调的框架,它支持多种微调方法,如LoRA、QLoRA等,并提供了丰富的数据集和预训练模型,便于用户进行模型微调。通义千问…

15:00面试,15:08就出来了,问的问题有点变态。。。

从小厂出来&#xff0c;没想到在另一家公司又寄了。 到这家公司开始上班&#xff0c;加班是每天必不可少的&#xff0c;看在钱给的比较多的份上&#xff0c;就不太计较了。没想到8月一纸通知&#xff0c;所有人不准加班&#xff0c;加班费不仅没有了&#xff0c;薪资还要降40%…

mysql 慢查询

一、开启mysql自己的慢查询日志 1、查看慢日志参数设置 show VARIABLES like %query% 2、修改配置文件 vim /etc/my.cnf [mysqld] slow_query_log 1 #是否开启慢查询日志记录 long_query_time 1 #慢查询时间&#xff0c;单位秒 #log_outputtable,file #慢查询…