【C++杂货铺】内管管理


目录

🌈前言🌈

📁 C/C++中内存分布

📁 new 和 delete的使用

📁 new 和 delete的优点

📁 new 和 delete的原理

 📂 operator new 和 operator delete函数

 📂 内置类型

 📂 自定义类型

📁 内存泄漏

📁 总结


🌈前言🌈

        欢迎收看本期【C++杂货铺】,本期内容讲解C++内存管理。包含了C++中内存分布情况,如何进行内存管理,使用new和delete操作符开辟/释放空间等,此外将介绍C++中new 和 delete的优点和原理。

        此外,本期内容可能会涉及到类和对象的部分概念,如果你还不是很了解,可以快速阅览以下文章:

【C++杂货铺】详解类和对象 [上]-CSDN博客

【C++杂货铺】详解类和对象 [中]-CSDN博客

【C++杂货铺】详解类和对象 [下]-CSDN博客

📁 C/C++中内存分布

        程序运行会被加载到内存,程序的代码和数据则会在内存中存储在不同地方,通过内存地址进行访问。

        内存地址是计算机中用来标识存储单元位置的一个唯一的数字。在计算机中,每个存储单元都有一个唯一的地址,通过这些地址可以访问和操作存储器中的数据。内存地址通常用十六进制表示。

        为了方便管理不同的类型的数据,如全局变量和局部变量,就会在内存中划分出不同区域。

当然这只是简单的了解一下内存分布,如果你学过操作系统的内容,你就会知道,C/C++中的内存概念其实都是虚拟内存,不是真实的物理内存。

        上图中,不同书籍可能会有偏差,如果只学过语言,只需要知道有栈,堆,数据段,代码段即可。其中栈存放局部变量,形参等数据,堆则是由程序员自己手动开辟,存放数据。

        所以,堆区则是我们进行内存管理的区域了。

📁 new 和 delete的使用

        学过C语言可能知道,想要在C语言中开辟内存空间需要使用malloc函数,释放资源使用free函数。

        下图是malloc和free函数的使用示例。

开辟1个int类型数据的空间
int* pa = (int*)malloc(sizeof(int));
if(pa == NULL )return 1;free(pa);开辟10个int类型数据的空间
int* parr = (int*)malloc(sizeof(int) * 10 );释放连续地址空间只需要给出首元素地址即可
free(parr);

        我们可以看出使用malloc函数非常的不方便,例如只开辟空间,不能完成初始化;需要手动判断内存是否开辟成功。

        此外,最重要的是,对于自定义类型,是需要构造函数初始化,但是malloc开完空间后,不能调用构造函数。

        所以C++语言就引入了两个操作符new 和 delete。

        下图是new 和 delete操作符的使用示例。

int* pa = new int;
delete pa;int* parr = new int[10];
delete[] parr;
        申请和释放单个元素的空间,使用 new delete 操作符,申请和释放连续的空间,使用 new[] delete[] ,注意:匹配起来使用

📁 new 和 delete的优点

        上文中,我们已经知道了new 和 delete 操作符的部分优点:

1. 编译器会自动检查内存空间是否成功开辟,如果失败,则会抛异常。

2. 可以完成初始化的工作。对于自定义类型,会调用它的构造函数和析构函数。

int* pa = new int(1);//如果是不完全初始化,后面会用0代替。
int* parr = new int(10){1,2,3,4,5};

📁 new 和 delete的原理

        以上我们简单了解了new和delete操作符的基本使用,想要彻底掌握,我们就从底层了解new和delete的区别以及底层实现。

 📂 operator new 和 operator delete函数

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

/*
operator new:该函数实际通过malloc来申请空间,当malloc申请空间成功时直接返回;申请空间
失败,尝试执行空间不足应对措施,如果改应对措施用户设置了,则继续申请,否则抛异常。
*/
void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
{
// try to allocate size bytes
void *p;
while ((p = malloc(size)) == 0)if (_callnewh(size) == 0){// report no memory// 如果申请内存失败了,这里会抛出bad_alloc 类型异常static const std::bad_alloc nomem;_RAISE(nomem);}
return (p);
}
/*
operator delete: 该函数最终是通过free来释放空间的
*/
void operator delete(void *pUserData)
{_CrtMemBlockHeader * pHead;RTCCALLBACK(_RTC_Free_hook, (pUserData, 0));if (pUserData == NULL)return;_mlock(_HEAP_LOCK);  /* block other threads */__TRY/* get a pointer to memory block header */pHead = pHdr(pUserData);/* verify block type */_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));_free_dbg( pUserData, pHead->nBlockUse );__FINALLY_munlock(_HEAP_LOCK);  /* release other threads */__END_TRY_FINALLYreturn;
}
/*
free的实现
*/
#define   free(p)               _free_dbg(p, _NORMAL_BLOCK)

        通过两个全局函数的实现就知道了,operator new 实际通过malloc来申请空间,如果malloc申请成功直接返回(原地扩容),否则执行用户提供的空间不足的措施(异地扩容),如果用户提供改措施,则会继续申请,否则抛异常。

         operator delete 最终通过free来释放空间。

 📂 内置类型

        如果申请的是内置类型的空间(int , double,指针...),new和malloc ,delete和free基本类似,不同之处在于:new 和 delete 是申请和释放单个元素空间,new[]和delete[]申请的是连续空间,释放连续的空间。而且new申请空间时会抛异常,malloc则会返回NULL。

 📂 自定义类型

        ● new的原理

        1. 调用operator new函数申请空间。

        2. 在申请的空间上执行构造函数,完成对象的构造。

        ● delete的原理

        1. 在空间上进行析构函数,完成对象资源的清理工作。

        2. 调用operator delete函数释放对象空间。

        ● new[ ]的原理 

        1. 调用operator new[ ]函数,在operator new[ ]中实际调用operator new函数完成 N个对象空间的申请。

        2. 在申请空间上调用N次构造函数。

        ● delete[ ]的原理

        1. 在释放对象的空间上进行N次析构函数,完成N个对象中资源的清理。

        2. 调用operator delete[ ]释放资源,实际在operator delete[ ]中调用operator delete[ ]了释放空间。

📁 内存泄漏

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

        

📁 总结

        以上,就是本期【C++杂货铺】内存管理的主要内容了,主要介绍了new和delete操作符的使用,有点及其底层原理。

        此外,简单介绍了C/C++中内存分布情况,以及内存泄露的基本概念和危害。

        如果感觉本期内容对你有帮助,欢迎点赞,收藏,关注Thanks♪(・ω・)ノ

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

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

相关文章

对iOS的内存存储的一些理解

最近写项目的时候遇到了一些内存上的问题(比如内存泄漏等等),通过网上的方法解决后,好奇iOS的数据是如何存储的,特记于此。 一、iOS的内存区域 iOS 中应用程序使用的计算机内存不是统一分配空间,运行代码使…

Javascript — 异步方法与异常捕获问题

问题:try catch为什么不能捕获未被 await 修饰的异步方法异常 async function throwError() {throw new Error("自定义Error!") }let testOne async () > {console.debug("start testOne")try {throwError()} catch (e) {conso…

【问题分析】InputDispatcher无焦点窗口ANR问题【Android 14】

1 问题描述 Monkey跑出的无焦点窗口的ANR问题。 特点: 1)、上层WMS有焦点窗口,为Launcher。 2)、native层InputDispacher无焦点窗口,上层为”recents_animation_input_consumer“请求了焦点,但是”rece…

大话设计模式之简单工厂模式

简单工厂模式(Simple Factory Pattern)是一种创建型设计模式,属于工厂模式的一种。在简单工厂模式中,有一个工厂类负责根据输入参数的不同来创建不同类的实例。 简单工厂模式包含以下几个要素: 1. **工厂类&#xff0…

太阳能发电园区3D可视化:揭秘绿色能源新纪元

在科技飞速发展的今天,绿色能源已成为推动社会进步的重要力量。太阳能发电作为绿色能源的重要代表,正在全球范围内掀起一股清洁能源的革命浪潮。 太阳能发电园区作为集中展示太阳能发电技术和应用的场所,其规模之大、设备之复杂,常…

ClickHouse03-小白如何快速搭建ClickHouse集群

普通测试通常使用ClickHouse单节点就可以了,但是生产环境不免需要考虑多活、负载等高可用问题,集群就成了基础需求 ClickHouse在集群的选择上,作者已知的有两种: 使用ZooKeeper作为节点协调的组件,使用ClickHouse-Kee…

算法---动态规划练习-7(按摩师)【类似打家劫舍】

按摩师 1. 题目解析2. 讲解算法原理3. 编写代码 1. 题目解析 题目地址:点这里 2. 讲解算法原理 首先,给定一个整数数组 nums,其中 nums[i] 表示第 i 天的预约时间长度。 定义两个辅助数组 f 和 g,长度都为 n(n 是数组…

201基于matlab的成绩管理系统

基于matlab的成绩管理系统。自带的GUI界面设计了一个成绩管理界面,可进行成绩的载入、查询、绘图、求平均分。可更改自己的数据进行录入。包含作业文档。程序已调通,可直接运行。 201 matlab 成绩管理系统 GUI - 小红书 (xiaohongshu.com)

C语言函数的定义、声明、调用与返回

在C语言中,函数是一种模块化和结构化的编程方式,用于封装特定的功能和逻辑。通过函数,可以将程序分解成多个小的模块,使得程序结构更清晰、易于理解和维护。本文将深入介绍C语言中函数的定义、声明、调用与返回,以帮助…

git的使用日常习惯规范与一些特殊操作

git的使用日常习惯规范与一些特殊操作 操作习惯规范创建本地新分支,推送新分支到云端仓库1.创建一个本地的login分支2.创建新分支后切换到新分支3.推送新分支到云端 git的特殊操作撤回commit(取消提交到本地版本库的动作,本地工作区写的代码不…

基于单片机锂电池电量检测数码管显示系统设计

**单片机设计介绍,基于单片机锂电池电量检测数码管显示系统设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机锂电池电量检测数码管显示系统设计的主要目标是实时、准确地检测锂电池的电量,并…

uniapp中安装vant2

1.uniapp项目搭建 因为是安装vant2所以项目选择vue2,如果vue3项目的话安装vant3 2.安装vant npm i vantlatest-v2 3.在main.js文件引入挂载vant 说明:// #ifndef VUE3这里是vue2模板用来挂载注册组件的地方;// #ifdef VUE3这里是vue3模板…

数据结构学习——链表面试题

1. 删除链表中等于给定值 val 的所有结点。 203. 移除链表元素 - 力扣(LeetCode) 方法一: struct ListNode* removeElements(struct ListNode* head, int val) {struct ListNode* prevNULL;struct ListNode* curhead;while(cur){if(cur-&…

海外媒体发稿:3种媒体宣发套餐内容推广方法

现如今,伴随着信息技术的不断进步和推广,新闻媒体宣发变成企业品牌推广的重要手段之一。为了方便让新闻信息新闻资讯传递给目标群体,公司一般会选择不同的套餐内容和推广方法。下面我们就详细介绍3种新闻资讯新闻媒体宣发套餐内容推广方法。 …

C# 操作 Word 全域查找且替换(含图片对象)

目录 关于全域查找且替换 Word应用样本 SqlServer数据表部分设计样本 范例运行环境 配置Office DCOM 设计实现 组件库引入 实现原理 查找且替换的核心代码 窗格内容 页眉内容 页脚内容 形状内容 小结 关于全域查找且替换 C#全域操作 Word 查找且替换主要包括如下…

【Java】ArrayList数组的扩容机制 jdk1.8

📝个人主页:哈__ 期待您的关注 ArrayList和普通数组不同,ArrayList支持动态扩容,那么ArrayList到底是如何扩容的呢?你又是否知道ArrayList数组的初始长度是多少呢? 在开始介绍之前,我们要先介…

【Python】如何安装Python

推荐安装python39版本 1.安装python1.1.在任意盘新建Python39目录1.2.双击安装包1.3.安装成功后,WINRcmd进入dos页面,输入 python,即可查看是否安装成功 2.环境变量配置2.1.打开 我的电脑-》高级系统设置-》环境变量-》系统变量2.2.如上图配置…

MHA高可用集群部署

一、MHA的概念 1.1 MHA概述 一套优秀的MySQL高可用环境下故障切换和主从复制的软件MHA的出现就是解决MySQL 单点的问题。 MySQL故障过程中,MHA能做到0-30秒内自动完成故障切换MHA能在故障切换的过程中最大程度上保证数据的一致性以达到真正意义上的高可用 …

​如何用“Dreamina”进行文生图​

文生图,顾名思义,就是用文字描述来生成图片。近年来,随着人工智能技术的进步,文生图技术也逐渐成熟,并逐渐应用于各种领域,例如设计、创作、娱乐等等。 本文将介绍如何使用“Dreamina”进行文生图。 步骤…

2024.3.25-26记:二叉树的遍历

二叉树的遍历深度优先遍历(DFS)递归遍历前序递归遍历:中序递归遍历后续递归遍历 非递归遍历前序非递归遍历中序非递归遍历后续非递归遍历 宽度优先遍历(BFS): 二叉树的遍历 二叉树遍历大体上分为深度优先遍历(DFS)和宽度优先遍历(BFS)&#…