Lesson 03 C/C++内存管理

news2024/11/15 12:09:36

C++:渴望力量吗,少年?

文章目录

  • 一、C++内存管理方式
    • 1. new/delete操作内置类型
    • 2. new和delete操作自定义类型
  • 二、operator new与operator delete函数
  • 三、new和delete的实现原理
    • 1. 内置类型
    • 2. 自定义类型
  • 四、内存泄漏
    • 1. 什么是内存泄漏
    • 2. 内存泄漏的危害
    • 3. 堆内存泄漏(Heap leak)
    • 4. 解决方案


一、C++内存管理方式

  C语言内存管理方式在C++中可以继续使用,但有些地方就无能为力,而且使用起来比较麻烦,因此C++又提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理。

1. new/delete操作内置类型

int main()
{
	// 动态申请一个int类型的空间
	int* ptr4 = new int;

	// 动态申请一个int类型的空间并初始化为10 
	int* ptr5 = new int(10);

	// 动态申请10个int类型的空间
	int* ptr6 = new int[3];

	delete ptr4;
	delete ptr5; 
	delete[] ptr6;

	// 额外支持开空间+初始化
	int* p6 = new int(10);//注意这里是赋值为10
	int* p7 = new int[10]{1,2,3};//和C语言一样,这种情况下没有初始化到的部分默认为0
	int* p8 = new int[10]{};

	return 0;
}

在这里插入图片描述

2. new和delete操作自定义类型

  在申请自定义类型的空间时,new会调用构造函数,delete会调用析构函数,而malloc与free不会。而他们对内置类型是几乎是一样的。

class A
{
public:
	A(int a = 0)
		: _a(a)
	{
		cout << "A():" << this << endl;
	}

	~A()
	{
		cout << "~A():" << this << endl;
	}

private:
	int _a;
};
int main()
{
	// malloc没有办法很好支持动态申请的自定义对象初始化
	A* p1 = (A*)malloc(sizeof(A));
	//p1->_a = 0;
	//p1->A(1);

	// 自定义类型,开空间的同时调用构造函数初始化
	A* p2 = new A;
	A* p3 = new A(3);

	// 自定义类型,调用析构函数+释放空间
	delete p2;
	delete p3;

	A* p4 = new A[10];
	delete[] p4;

/*下面三种写法都是一样的
	A aa1(1);
	A aa2(2);
	A* p5 = new A[10]{ aa1, aa2 };
	delete[] p5;

	A* p6 = new A[10]{ A(1), A(2) };
	delete[] p6;

	A* p7 = new A[10]{ 1, 2 };
	delete[] p7;
*/
	return 0;
}

二、operator new与operator delete函数

  new和delete是用户进行动态内存申请和释放的操作符,operator new 和operator delete是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间。
  operator new:该函数实际通过malloc来申请空间,当malloc申请空间成功时直接返回;申请空间失败,尝试执行空间不足应对措施,如果改应对措施用户设置了,则继续申请,否则抛异常

typedef char DataType;
class Stack
{
public:
	Stack(size_t capacity = 4)
	{
		cout << "Stack()" << endl;

		_array = new DataType[capacity];//析构函数对应也得用delete释放空间
		//_array = new char[0x7ffffffffff];//如果取消注释,那么对应的第二段代码会抛出异常

		_capacity = capacity;
		_size = 0;
	}

	void Push(DataType data)
	{
		// CheckCapacity();
		_array[_size] = data;
		_size++;
	}

	~Stack()
	{
		cout << "~Stack()" << endl;

		delete[] _array;
		_array = nullptr;
		_size = _capacity = 0;
	}
private:
	// 内置类型
	DataType* _array;
	int _capacity;
	int _size;
};
class A
{
public:
	A(int a = 0)
		:_a1(a)
	{}

	~A()
	{
		cout << "~A()" << endl;
	}

private:
	int _a1;
};
int main()
{
	Stack* pst1 = (Stack*)operator new(sizeof(Stack));//相当于malloc,创造它是为了符合抛出异常的方式
	operator delete(pst1);//相当于free
	//其实上面两个函数主要都不是让我们直接使用,而是分别封装在new和delete中,new就相当于operator new和调用构造函数

	Stack* pst2 = new Stack;
	delete pst2;
	//free(pst2);

	A* p2 = new A[10];
	delete[] p2;
	return 0;
}

  new和delete一定要匹配使用,否则后果可能是未定义的!!!

三、new和delete的实现原理

1. 内置类型

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

2. 自定义类型

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

四、内存泄漏

1. 什么是内存泄漏

  内存泄漏指因为疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并不是指内存在物理上的消失,而是应用程序分配某段内存后,因为设计错误,失去了对该段内存的控制,因而造成了内存的浪费。

2. 内存泄漏的危害

  长期运行的程序出现内存泄漏,影响很大,如操作系统、后台服务等等,出现内存泄漏会导致响应越来越慢,最终卡死。

void MemoryLeaks()
{
	// 1.内存申请了忘记释放
	int* p1 = (int*)malloc(sizeof(int)); 
	int* p2 = new int;

	// 2.异常安全问题
	int* p3 = new int[10];
	Func(); 
	// 这里Func函数抛异常导致 delete[] p3未执行,p3没被释放. 
	delete[] p3;
}

3. 堆内存泄漏(Heap leak)

  作为初学者,我们更加关注的是这方面的泄露。堆内存指的是程序执行中依据须要分配通过malloc / calloc / realloc / new等从堆中分配的一块内存,用完后必须通过调用相应的 free或者delete 删掉。假设程序的设计错误导致这部分内存没有被释放,那么以后这部分空间将无法再被使用,就会产生Heap Leak。

4. 解决方案

内存泄漏非常常见,一般解决方案分为两种:
(1)事前预防型。如智能指针等;
(2)事后查错型。如泄漏检测工具。


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

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

相关文章

Python字典六种类型概述

1. 引言 看到这个标题&#xff0c;你可能会觉得奇怪&#xff0c;事实上在Python的标准库中共有6种字典类型&#xff01;在某些情形下&#xff0c;你可能会觉得标准的Python字典dict&#xff0c;并不能完全符合你的需求。在本文中&#xff0c;我们将讨论Python中其他5个鲜为人知…

[最新榜单] 智能手机数据恢复的 10 款最佳应用

当手机上的数据消失时&#xff0c;这让您感到非常难过。 由于事故而突然丢失重要的聊天记忆、照片和其他您想保留的东西的悲伤。 如果它没有被淹没&#xff0c;您可以使用数据恢复应用程序修复它。 在本文中&#xff0c;我们将解释一些有用的数据恢复应用程序。 数据恢复应用…

【LeetCode】每日一题 2023_11_18 数位和相等数对的最大和(模拟/哈希)

文章目录 刷题前唠嗑题目&#xff1a;数位和相等数对的最大和题目描述代码与解题思路思考解法偷看大佬题解结语 刷题前唠嗑 LeetCode? 启动&#xff01;&#xff01;&#xff01; 本月已经过半了&#xff0c;每日一题的全勤近在咫尺~ 题目&#xff1a;数位和相等数对的最大和…

【数据结构】树与二叉树(十九):树的存储结构——左儿子右兄弟链接结构(树、森林与二叉树的转化)

文章目录 5.1 树的基本概念5.1.1 树的定义5.1.2 森林的定义5.1.3 树的术语 5.2 二叉树5.3 树5.3.1 树的存储结构1. 理论基础2. 典型实例3. Father链接结构4. 儿子链表链接结构5. 左儿子右兄弟链接结构a. 定义树节点b. 创建树节点c. 使用左儿子右兄弟链接结构将树转化为二叉树d.…

从0开始学习JavaScript--JavaScript 表达式与运算符

JavaScript中的表达式和运算符是构建逻辑、进行计算的基础。本文将深入研究JavaScript中各类表达式&#xff0c;包括算术表达式、关系表达式、逻辑表达式&#xff0c;以及运算符的使用方法&#xff0c;并通过丰富的示例代码来帮助读者更全面地了解和运用这些概念。 算术表达式…

和鲸 ModelWhale 入驻华为蓝鲸应用商城,助力大模型时代 AI 赋能应用落地

近日&#xff0c;和鲸旗下数据科学协同平台 ModelWhale 成功入驻华为蓝鲸应用商城&#xff0c;这也是继和鲸与华为发布数据分析建模实训联合解决方案后的再度携手&#xff0c;标志着双方的合作进入更全面、更深入的新阶段。 华为蓝鲸应用商城是华为数据存储面向客户提供的一站…

【选题推荐】软件工程毕设选题可以选什么

文章目录 0 简介1 如何选题2 最新软件工程毕设选题3 最后 0 简介 学长搜集分享最新的软件工程业专业毕设选题&#xff0c;难度适中&#xff0c;适合作为毕业设计&#xff0c;大家参考。 学长整理的题目标准&#xff1a; 相对容易工作量达标题目新颖 1 如何选题 最近非常多的…

【Mysql】复合查询详解+实战操作(多表查询、自链接、子查询等)

&#x1f308;欢迎来到Python专栏 &#x1f64b;&#x1f3fe;‍♀️作者介绍&#xff1a;前PLA队员 目前是一名普通本科大三的软件工程专业学生 &#x1f30f;IP坐标&#xff1a;湖北武汉 &#x1f349; 目前技术栈&#xff1a;C/C、Linux系统编程、计算机网络、数据结构、Mys…

网络协议头分析及抓包三次挥手四次握手

数据的封装与传递过程 思考&#xff1a; 应用层调用send后&#xff0c;是如何把数据发送到另一台机器的某个进程的。接收的设备收到数据包后&#xff0c;如何处理给应用层&#xff1f; MTU &#xff1a; Maximum Transmit Unit 最大传输单元 物理接口&#xff08;数据链路层&am…

vmware workstation pro 17.5 安装 macos 13.5.2 虚拟机超详细图文教程

前言 本文很细&#xff0c;甚至有点墨迹&#xff0c;主要为了方便从来没用过 vmware 的新人&#xff0c;其实大部分步骤和正常安装虚拟机没有区别&#xff0c;详细贴图以方便大家对比细节 参考文章 感谢大佬们的无私分享 https://blog.csdn.net/qq_19731521/article/details…

Linux下非root用户安装CUDA

目录 前言 参考链接 步骤 一. 首先&#xff0c;需要查看系统版本&#xff1a; 二. 安装包下载。 下载CUDA&#xff1a; cuDNN下载 三. 开始安装CUDA和cuDNN 安装CUDA 修改环境变量 安装 cuDNN 查看是否安装成功&#xff0c;输入nvcc -V 前言 由于一些代码实现&…

基于社会群体算法优化概率神经网络PNN的分类预测 - 附代码

基于社会群体算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于社会群体算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于社会群体优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神…

Google大法好

Google Search Central 前言&#xff1a; google的搜索方式&#xff1a; Google 是一款全自动搜索引擎&#xff0c;会使用名为“网页抓取工具”的软件定期探索网络&#xff0c;以找出可添加到 Google 索引中的网站。实际上&#xff0c;Google 搜索结果中收录的大多数网站都不…

BGP的基础知识

BGP——边界网关协议 IGP——内部网关协议——OSPF、RIP、ISIS EGP——外部网关协议——EGP、BGP 边界网关协议BGP是一种实现自治系统AS之间的路由可达&#xff0c;并选择最佳路由的路径矢量路由协议。目前在IPV4环境下主要使用BGPV4&#xff0c;目前市场上也存在BGPV4&…

uniapp优化h5项目-摇树优化,gzip压缩和删除console.log

1.摇树优化 勾选摇树优化,打包删除死代码 2.gzip压缩和删除console.log 安装插件webpack和compression-webpack-plugin webpack插件 npm install webpack4.46.0 --save-devcompression-webpack-plugin插件 npm install compression-webpack-plugin6.1.1 --save-devconst Com…

java+ 如何动态配置业务规则组

思路 1. 实现在页面上的动态配置规则组&#xff08;2张数据表枚举类serviceimplaction&#xff09; 2. 从数据库中表staffmoverules&#xff08;规则明细表&#xff09;或者staffmovetyperule&#xff08;规则组表&#xff09; &#xff0c;根据传入类型&#xff0c;取出规则编…

[C/C++]数据结构 栈和队列()

一:栈 1.1 栈的概念及结构 栈是一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作,进行数据插入和删除操作的一端称为栈顶,另一端称为栈底,栈中的数据元素遵守先进后出的原则. 压栈:栈的插入操作叫做进栈/压栈/入栈,将数据插入栈顶 出栈:栈的删除操作也叫出…

自学嵌入式,已经会用stm32做各种小东西了

自学嵌入式&#xff0c;已经会用stm32做各种小东西了 1、stm32 工程中&#xff0c;定义一个变量&#xff0c;记录复位次数&#xff0c;即复位一次变量加一。要求不许用备份寄存器和 flash 保存信息。本题只讨论不断电热启动情况&#xff0c;至于冷启动&#xff0c;不在此讨论。…

整理MLAI学习路径图

干货分享&#xff1a; 下面给出一个笔者自己整理的GitHub仓库&#xff1a;https://github.com/isLinXu/awesome-road-map&#xff0c;里面包含了一些可供参考的学习路径和思维导图&#xff0c;并整理微软、meta、谷歌、Kaggle以及华为、百度、阿里、腾讯、讯飞等相关的学习资源…

stm32入门建议跳过固件库去学习hal库吗?

stm32入门建议跳过固件库去学习hal库吗? 如果要以单片机作为以后的工作方向&#xff0c;建议还是深入了解一下单片机的原理与机制&#xff0c;比如串口收发的时候&#xff0c;内部的寄存器是怎么工作的&#xff0c;中断又是怎么工作的&#xff0c;然后我们又是怎么进行中断处…