C++——内存管理(new和delete)详解

目录

C/C++内存管理

案例:变量在内存中到底会在哪?

New和delete

Operator new和operator delete函数

New和delete的原理

对内置类型

对自定义类型

定位new

New/delete和malloc/free的区别


C/C++内存管理

        C/C++内存管理分布图:(从语言的角度来看,数据段也称为静态区,代码段也称为常量区)

        内存大小:理论上,32位计算机内存上限为4GB;64位计算机内存上限可达256T,实际上我们使用计算机一般为8G或16G或者32G,不会很大。

栈和堆细节:  

        栈区先定义的变量放到栈底地址高后定义的变量放到栈顶地址低,因此是栈是向下生长的,堆区则相反

        栈区主要存在局部变量和函数参数,其空间的管理由编译器自动完成,无需手动控制,堆区是自己申请。

        堆大小受限于操作系统,而栈空间一般由系统直接分配。

        栈一般是进行静态分配的,但也可以通过函数_alloca进行动态分配,不过注意,所分配空间不能通过free或delete进行释放,而堆无法静态分配,只能动态分配。

         在C语言中我们用malloc/calloc/realloc和free来在堆上管理堆上的空间,但在c++中进行了更新。在C++中我们用New和delete来管理堆上的空间。

        Malloc和new的最大差别是:C语言malloc失败后会返回NULL,C++New失败后会自动报异常。

        注意:使用malloc是需要头文件malloc.h,只是平时这个头文件已经被其他头文件所包含了,用的时候很少单独引入。

案例:变量在内存中到底会在哪?

请填写下列问题:

        globalVar在哪里?__静态区__  staticGlobalVar在哪里?_静态区___

        staticVar在哪里?__静态区__  localVar在哪里?____

        num1 在哪里?____

        char2在哪里?____ * char2在哪里?___

用数组存储字符串,会在代码段生成一串字符,然后到栈上开辟一段空间,把内容拷贝进去

        pChar3在哪里?____ * pChar3在哪里?_代码段(常量区)___

用指针则是存放 代码段内存放字符串的地址,所以解引用地址会在代码段

        ptr1在哪里?____ * ptr1在哪里?____

prt1变量是在栈区创建的,所以在栈上,但申请的空间在堆上

        sizeof(num1) = __40__;

        sizeof(char2) = _5___;   strlen(char2) = __4__;(sizeof(数组)就是整个数组的大小

        sizeof(pChar3) = _4/8___;   strlen(pChar3) = _4___;(sizeof(指针)则是看几位计算机

        sizeof(ptr1) = __4/8__;

New和delete

        创建单个对象:new 类型(内容)创建数组:new 类型[大小]{内容},开辟类对象的数组时(该类对象有用户写的析构函数,默认生成的不行),会在前面额外开辟4字节空间,用于存放类对象数组有多少个元素,让delete数组时,调用类的析构函数时知道要调用几次。C++把new当做一个操作符而不是函数

        Delete也分为两种,释放单个空间:delete 对象名;释放一个数组:delete[] 对象名

        New和delete的使用方式如下:

        在C++中,我们new一个类对象,编译器会自动调用该类的构造函数。这样就不需要像C语言malloc一个空间然后赋值那么麻烦。Delete也会调用该类的析构函数。

注意:new和delete一定要匹配使用,即new数组要用delete数组来释放。

        如果不匹配使用,对于内置类型没有自己写析构函数的类一般不会出错(默认生成析构函数是系统合成的没有作用的析构函数,所以系统什么也不做,只用释放空间,内置类型同理

        对于有自己写析构函数的类,delete会调用析构函数,而new数组本来应该匹配delete数组来释放,让编译器调用多次析构函数,但如果我们没有匹配使用,如下图,只用了delete a1,编译器只会调用一次析构函数,编译虽然能通过,但是运行会出断言错误。

Operator new和operator delete函数

        Operator new和operator delete函数是系统提供的全局函数,它们实际上是new和delete的底层代码,new底层会调用operator new函数来申请空间;delete底层调用operator delete函数来释放空间

        Operator new底层代码也是通过malloc来开辟空间,即对malloc的封装,如果空间不够,则判断一下malloc是否返回NULL;如果申请内存失败了,这里会抛出bad_alloc类型异常,也就是new失败之后返回的异常。Operator delete同理,是对free的封装

        总之,operator new不是为我们准备的,而是为new准备的,主要是用来返回开辟空间异常的

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个对象中资源的清理。(N是多少编译器会知道,不需要填),然后调用operator delete[]释放空间,实际上在operator delete[]中会调用operator delete来释放空间。

定位new

        定位new表达式是已分配的原始内存空间中调用构造函数初始化一个对象。使用方法为:new(指针,指向开辟的空间)类型(要初始化的值),使用情况如下图所示:

New/delete和malloc/free的区别

区别:

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

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

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

相关文章

内网搭建mysql8.0并搭建主从复制详细教程!!!

一、安装mysql 1.1 mysql下载链接: https://downloads.mysql.com/archives/community/ 1.2 解压包并创建相应的数据目录 tar -xvf mysql-8.2.0-linux-glibc2.28-x86_64.tar.xz -C /usr/local cd /usr/local/ mv mysql-8.2.0-linux-glibc2.28-x86_64/ mysql mkdir…

纯css实现-让字符串在文字少时显示为居中对齐,而在文字多时显示为左对齐

纯css实现-让字符串在文字少时显示为居中对齐,而在文字多时显示为左对齐 使用flex实现 思路 容器样式(.container): Flex容器的BFC性质使得其内部的子元素(.text-box)在水平方向上能够居中,通过justify-c…

《TCP/IP详解 卷一》第9章 广播和组播

目录 9.1 引言 9.2 广播 9.2.1 使用广播地址 9.2.2 发送广播数据报 9.3 组播 9.3.1 将组播IP地址转换为组播MAC地址 9.3.2 例子 9.3.3 发送组播数据报 9.3.4 接收组播数据报 9.3.5 主机地址过滤 9.4 IGMP协议和MLD协议 9.4.1 组成员的IGMP和MLD处理 9.4.2 组播路由…

如何实现WordPress后台显示文章、分类目录、标签等的ID?

我们平时在使用WordPress的过程中,偶尔需要用到文章的ID,或分类目录ID,或标签ID,或媒体库ID,或评论ID,或用户ID等,但是WordPress后台默认是不显示它们的ID的。 今天boke112百科就跟大家分享如何…

c语言经典测试题8

在c语言经典测试题6的第一题,大家是否想过可不可以将递归参数改为s呢?或许有的人已经试过了,但是发现好像不会有结果,其实是因为s为后置,先试用后加1,然而我们这个是在s出了函数之后才会运行加1操作&#x…

新版极狐gitlab安装+配置详细版

这里安装的服务器环境是centos7.9系统,安装极狐版本16.9。 极狐地址:https://gitlab.cn/install/ 1. 安装和配置所需的依赖 在 CentOS 7 上,下面的命令会在系统防火墙中打开 HTTP、HTTPS 和 SSH 访问。这是一个可选步骤,如果您…

【Linux C | 网络编程】getaddrinfo 函数详解及C语言例子

😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀 🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C、数据结构、音视频🍭 🤣本文内容🤣&a…

生成式 AI - Diffusion 模型的数学原理(5)

来自 论文《 Denoising Diffusion Probabilistic Model》(DDPM) 论文链接: https://arxiv.org/abs/2006.11239 Hung-yi Lee 课件整理 讲到这里还没有解决的问题是,为什么这里还要多加一个噪声。Denoise模型算出来的是高斯分布的均…

【Leetcode每日一刷】哈希表|纲领、242.有效的字母异位词、349. 两个数组的交集

纲领 🔗代码随想录理论部分 关于哈希表这个数据结构就不再重复讲了,下面对几个关键点记录一下: 哈希碰撞 解决方法1:拉链法 解决方法2:线性探测法 下面针对做题要用到的三种结构讲一下(也是重复造轮子了…

Spring AI上架,打造专属业务大模型,AI开发再也不是难事!

Spring AI 来了 Spring AI 是 AI 工程师的一个应用框架,它提供了一个友好的 API 和开发 AI 应用的抽象,旨在简化 AI 应用的开发工序。 提供对常见模型的接入能力,目前已经上架 https://start.spring.io/,提供大家测试访问。&…

Docker技术概论(1):Docker与虚拟化技术比较

Docker技术概论(1) Docker与虚拟化技术比较 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at: https://jclee95.blog.csdn.netMy WebSite:http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https:…

cpp基础学习笔记03:类型转换

static_cast 静态转换 用于类层次结构中基类和派生类之间指针或者引用的转换。up-casting (把派生类的指针或引用转换成基类的指针或者引用表示)是安全的;down-casting(把基类指针或引用转换成子类的指针或者引用)是不安全的。用于基本数据类型之间的转换&#xff…