【C++指南】内存管理完全手册:new/delete

news2025/3/19 9:21:05

🌟 各位看官好,我是egoist2023

🌍 种一棵树最好是十年前,其次是现在!

🚀 今天来学习C++内存管理的相关知识。

👍 如果觉得这篇文章有帮助,欢迎您一键三连,分享给更多人哦

目录

内存分布

内存管理

new和delete实现原理

operator new与operator delete函数

内置类型

自定义类型

定位new

malloc/free和new/delete的区别


内存分布

在上图中,各部分变量分配在 A.栈   B.堆   C.数据段(静态区)    D.代码段(常量区)  哪个区域呢?

  1. globalVar是全局变量在数据段;
  2. staticGlobalVar是静态全局变量,同样在静态区;
  3. staticVar由于static的修饰,是静态局部变量,因此也在静态区;
  4. 非静态局部变量、数组都是存在栈区。因此num1,char2都是在栈区;
  5. char2是一个数组,把后面常量串拷贝过来到数组中,数组在栈上,所以*char2是在栈上的;

          6.pChar3和ptr1都是指针变量,是存在栈区上的。因为是指针,pChar3是指向字符串的,字符串是在常量区的,因此*pChar3是在常量区的。ptr1指向的是堆区上的一块空间,因此*ptr1得到的是动态申请空间的数据在堆区。

    1. 又叫堆栈 -- 非静态局部变量 / 函数参数 / 返回值等都是在栈区的,栈是向下增长的。
    2. 内存映射段 是高效的 I/O 映射方式,用于装载一个共享的动态内存库。用户可使用系统接口
    创建共享共享内存,做进程间通信。
    3. 用于程序运行时动态内存分配,如malloc、calloc都是向堆区申请空间,堆是向上增长的。
    4. 数据段(静态区) -- 存储全局数据和静态数据。
    5. 代码段(常量区) -- 可执行的代码 / 只读常量,如字符串。

    内存管理

    new和delete实现原理

    在C语言中,动态内存管理方式有:malloc/calloc/realloc/free。

    由于C语言的使用过于麻烦和一些缺陷(只能分配空间,需要手动初始化之类)。在C++中引入了newdelete操作符进行动态内存管理

    new和delete的简单使用

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

    动态申请n个空间时,与delete[]搭配使用。new和delete似乎只是简化了C语言中的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()
    {
    	// 内置类型是几乎是一样的
    	int* p3 = (int*)malloc(sizeof(int)); // C
    	int* p4 = new int;
    	free(p3);
    	delete p4;
    
        // 自定义类型
        A* p1 = (A*)malloc(sizeof(A));
    	A* p2 = new A(1);
    	free(p1);
    	delete p2;
    
    	A* p5 = (A*)malloc(sizeof(A) * 10);
    	A* p6 = new A[10];
    	free(p5);
    	delete[] p6;
    	return 0;
    }

    通过调试发现在针对内置类型时,new和malloc都是动态申请了一块内存,几乎是一样的;

    但在针对自定义类型时,new先开了一块空间,然后再去调用了构造函数。delete同理在针对自定义类型时也会去调用对应的析构函数。因此new/delete malloc/free最大区别是new/delete除了申请/销毁空间还会调用对应构造/析构函数。

    即new = 开空间 + 构造函数 , delete = 析构函数 + 销毁空间 。

    operator newoperator delete函数

    new/delete的开/销毁空间与malloc/free有什么区别呢?

    实际上new底层是调用operator new全局函数来申请空间,delete在底层通过 operator delete全局函数来释放空间。

    而operator new函数实际是对malloc进行了封装,operator delete函数是对free进行了封装。区别在于若申请空间不足或出错时,采用了抛异常的玩法,不会终止程序(后续章节会讲到)。

    内置类型

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

    自定义类型

    new的原理
    调用 operator new 申请空间
    构造函数
    delete的原理
    析构函数
    调用 operator delete 释放空间
    new T[N] 的原理
    调用operator new[]函数,实际调用operator new函数完成N个对象空间的申请
    申请空间上执行 N 次构造函数
    delete[] 的原理
    空间上执行 N 次析构函数
    调用operator delete[]释放空间,实际调用operator delete来释放空间

    定位new

    定义:为已分配的原始内存空间中调用构造函数初始化一个对象

    使用方式:new(place_address) type或new(place_address) type(initializer-list)

    place_address 必须是一个指针, initializer-list 是类型的初始化列表。如:
    new (p) A;

     那什么时候会用到定位new呢?一般是与内存池(池化技术)搭配使用,因为内存池的内存并未初始化,需要new来帮助自定义类型对象调用构造函数完成初始化。这里浅浅地了解下内存池。

    应用场景:malloc、calloc都是向堆中申请内存,但如果申请频繁的话,就会增大系统内存分配函数的开销,因此需要借助内存池来减少开销。实际上,stl库中很多都用到了内存池的技术,如vector。

    malloc/freenew/delete的区别

    它们都是从堆上申请空间,不同点如下。

    malloc/freenew/delete
    函数操作符
    不会初始化初始化
    手动计算空间大小其后跟上空间类型,申请多个对象,用[]指定个数
    返回值为void*,要强转不需要强转
    申请失败,返回NULL

    抛异常

    开/销毁空间开/销毁空间+构造/析构

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

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

    相关文章

    Vue3组合式函数(滚动监测 useScroll)

    主要用于实时监测目标元素滚动位置及状态 工具函数源码 /*** 组合式函数* 实时监测目标元素滚动位置及状态** 自定义钩子用于处理滚动事件和状态* param target 滚动目标元素&#xff0c;可以是 Ref、HTMLElement、Window 或 Document&#xff0c;默认为 window* param throt…

    Vue.js+Element UI 登录界面开发详解【附源码】

    成果图&#xff1a; 一、技术架构解析 本登录模块采用前后端分离架构&#xff0c;前端基于Vue.jsElement UI实现交互逻辑&#xff0c;主要包含以下技术要点&#xff1a; ​组件化开发 - 采用单文件组件形式组织代码​响应式设计 - 实现多终端适配​状态管理 - 使用sessionSto…

    瑞幸需要宇树科技

    吃不到“星巴克红利”&#xff0c;瑞幸活成“Manner”。 作者|古廿 编辑|杨舟 “是不是又要开始3月革命了。”有瑞幸员工透露&#xff0c;今年开始瑞幸加强了系统排班的执行力度。新的排班体系下&#xff0c;要求各时段门店实际值班人员和排班系统一致。如果需要调整&#xf…

    linux 命令 vim

    以下是 Linux 中 Vim 编辑器的核心命令总结&#xff0c;分为基础操作、高效编辑技巧和实用场景&#xff0c;助你快速掌握 1. 启动与退出 命令说明vim 文件名打开或新建文件vim 行号 文件名打开文件并跳转到指定行&#xff08;如 vim 10 file.txt&#xff09;:q退出 Vim&#…

    解决MySQL字符集冲突引发的“Illegal mix of collations”错误

    引言 在开发过程中&#xff0c;我们常常会遇到数据库层面的字符集兼容性问题。本文将通过一个典型的案例&#xff0c;分析因字符集不匹配导致的 Illegal mix of collations 错误&#xff0c;并提供完整的解决方案&#xff0c;帮助开发者彻底规避此类问题。 问题现象 假设我们…

    Vue中的publicPath释义

    publicPath 部署应用包时的基本URL。用法和 webpack 本身的 output.publicPath 一致&#xff0c;但是 Vue CLI 在一些其他地方也需要用到这个值&#xff0c;所以请始终使用 publicPath 而不要直接修改 webpack 的 output.publicPath。 默认情况下&#xff0c;Vue CLI 会假设你…

    新造车不再比拼排名,恰是曲终人散时,剩者为王

    据称新能源汽车周销量不再发布&#xff0c;这可能也预示着新造车终于到了给出答案的时候了&#xff0c;新造车企业前三强已基本确立&#xff0c;其余那些落后的车企已很难有突围的机会&#xff0c;而特斯拉无疑是其中的最大赢家。 3月份第一周的数据显示&#xff0c;销量最高的…

    博客迁移----宝塔面板一键迁移遇到问题

    前景 阿里云轻量级服务器到期了&#xff0c;又免费领了个ESC&#xff0c; 安转了宝塔面板。现在需要迁移数据&#xff0c;使用宝塔面板一键迁移功能&#xff0c;完成了数据的迁移&#xff0c;改了域名的解析&#xff0c;现在进入博客是显示502 bad grateway 宝塔搬家参考链接…

    大数据处理最容易的开源平台

    大数据处理最容易的开源平台可以从多个角度进行分析&#xff0c;包括易用性、灵活性、成本效益以及社区支持等方面。 Apache Spark Apache Spark 是一个广泛使用的开源大数据处理框架&#xff0c;以其快速、通用和易于使用的特点而著称。它支持多种编程语言&#xff08;如 Scal…

    Dify 使用 - 创建 翻译 工作流

    文章目录 1、选择 模板2、设置 和 基本使用3、运行应用 1、选择 模板 2、设置 和 基本使用 翻译模板 自带了系统提示词&#xff0c;你也可以修改 3、运行应用 右上角 点击 发布 – 更新&#xff0c;运行应用&#xff0c;就可以在新的对话界面中使用此功能 2025-03-18&#x…

    TreelabPLMSCM数字化供应链解决方案0608(61页PPT)(文末有下载方式)

    详细资料请看本解读文章的最后内容。 资料解读&#xff1a;TreelabPLMSCM 数字化供应链解决方案 0608 在当今快速变化的市场环境中&#xff0c;企业面临着诸多挑战&#xff0c;Treelab 数智化 PLM_SCM 行业解决方案应运而生。该方案聚焦市场趋势与行业现状&#xff0c;致力于解…

    LogicFlow介绍

    LogicFlow介绍 LogicFlow是一款流程图编辑框架&#xff0c;提供了一系列流程图交互、编辑所必需的功能和灵活的节点自定义、插件等拓展机制。LogicFlow支持前端自定义开发各种逻辑编排场景&#xff0c;如流程图、ER图、BPMN流程等。在工作审批流配置、机器人逻辑编排、无代码平…

    [蓝桥杯 2023 省 B] 飞机降落

    [蓝桥杯 2023 省 B] 飞机降落 题目描述 N N N 架飞机准备降落到某个只有一条跑道的机场。其中第 i i i 架飞机在 T i T_{i} Ti​ 时刻到达机场上空&#xff0c;到达时它的剩余油料还可以继续盘旋 D i D_{i} Di​ 个单位时间&#xff0c;即它最早可以于 T i T_{i} Ti​ 时刻…

    应用分层简介

    一、什么是应用分层 应用分层是一种软件开发设计思想&#xff0c;它将应用程序分为多个层次&#xff0c;每个层次各司其职&#xff0c;多个层次之间协同提供完整的功能&#xff0c;根据项目的复杂程度&#xff0c;将项目分为三层或者更多层。 常见的MCV设计模式&#xff0c;就…

    基于香橙派 KunpengPro学习CANN(3)——pytorch 模型迁移

    通用模型迁移适配可以分为四个阶段&#xff1a;迁移分析、迁移适配、精度调试与性能调优。 迁移分析 迁移支持度分析&#xff1a; 准备NPU环境&#xff0c;获取模型的源码、权重和数据集等文件&#xff1b;使用迁移分析工具采集目标网络中的模型/算子清单&#xff0c;识别第三方…

    电子硬件入门(三)——偏置电路

    文章目录 一、先理解问题&#xff1a;为什么需要偏置电压&#xff1f;二.偏置电路生成的四大核心零件​三、工作流程图解​四、实物电路对照​五、常见问题答疑 一、先理解问题&#xff1a;为什么需要偏置电压&#xff1f; 想象一下&#xff0c;电机的电流像一条波浪线&#x…

    使用C++写一个递推计算均方差和标准差的用例

    文章目录 代码输出关键实现说明1. 类设计2. 算法核心3. 数值稳定性 扩展应用场景1. 实时传感器数据处理2. 大规模数据集分块处理 总结 以下是用 C 实现递推计算均值、方差和标准差的完整示例代码&#xff0c;基于 Welford 算法&#xff0c;适用于实时数据流或大数据场景&#x…

    Vue:单文件组件

    Vue&#xff1a;单文件组件 1、 什么是单文件组件&#xff1f; 在传统的Vue开发里&#xff0c;我们接触的是非单文件组件&#xff0c;它们通常被定义在同一个HTML文件中&#xff0c;随着项目规模的扩大&#xff0c;代码会变得杂乱无章&#xff0c;维护起来极为困难。而单文件…

    JavaScript变量声明与DOM操作指南

    变量声明 1.变量声明有三个 var let 和 const 我们应该用那个呢&#xff1f; 首先var 先排除&#xff0c;老派写法&#xff0c;问题很多&#xff0c;可以淘汰掉… 2.let or const ? 建议&#xff1a; const 优先&#xff0c;尽量使用const&#xff0c;原因是&#xff1a;…

    [K!nd4SUS 2025] Crypto

    最后一个把周末的补完。这个今天问了小鸡块神终于把一个补上&#xff0c;完成5/6&#xff0c;最后一个网站也上不去不弄了。 Matrices Matrices Matrices 这个是不是叫LWE呀&#xff0c;名词忘了&#xff0c;但意思还是知道。 b a*s e 这里的e是高斯分成&#xff0c;用1000…