C++内存管理(new与delete)

这篇文章的主要内容是new与delete的由来,使用new与delete对C++堆内存进行管理,(malloc、free)与(new、delete)的区别。希望对C++爱好者有所帮助,内容充实且干货,点赞+收藏防止找不到!

更多C++优质内容跳转:

重生之C++启程(文章平均质量分93)

目录

1.malloc、free向new delete的转变

2.new与delete基础语法

3.(malloc、free)与(new、delete)的区别(面试高频)


 

1.malloc、free向new delete的转变

我们知道,在C语言学习阶段,用malloc来申请堆上的内存空间,free来释放堆上的内存空间。但是为什么C++中要引入new与delete呢?祖师爷设计的一定有他的道理。

接下来用代码来一步一步实操分析:

int main()
{
	int n = 3;
	int* pa =(int*)malloc(sizeof(int) * n);
    free(pa);//C语言手动释放空间
	return 0;
}

在C语言中,这样的代码是向堆上动态申请n个存储int类型对象的连续空间。将空间地址传给指针pa。free(pa)手动释放掉这块申请的堆空间。

那么用C++中的new、delete怎么操作呢? 

int main()
{
	int n = 3;
	int* pa = new int[n];
	delete[] pa;//C++手动释放空间
	return 0;
}

这样一看,C++的方式好像更简便一些。用调试,监视窗口看看二者的初始化情况:

这是malloc

870f62b1b63b40d880d341d5163af366.png

由图可见,malloc申请空间后并没有为其空间的内容初始化。那new呢?

这是new

c6bd6404afc643abaefaad5eaa91699e.png

由图可见,new也一样没有对堆上申请的这块空间内容初始化。 那我们可以得出结论:malloc和new相同,都不会初始化内容,只是new的使用更加简便吗?(那就格局太小了!)

答案是否定的,上面我们举的例子是对于内置类型的,让我们来对比malloc与new在自定义类型上的表现。

#include<iostream>
using namespace std;
class A
{
public:
	A(int x=0)
		:_a(x)
	{
		cout << "A()" << endl;
	}
private:
	int _a;
};
int main()
{
	A* pa = (A*)malloc(sizeof(A));//开空间,不会调用构造函数,尴尬了
	free(pa);
	
	A* pb = new A;//开空间+调用构造函数
	delete pb;
	return 0;
}

我们知道,malloc自定义类型只会为对象的成员变量开辟一块空间,并不会进行初始化。也就是说malloc申请的堆空间上的对象没有调用构造函数。只是单纯开好了空间。 但又不能显示调用构造函数。此时会很尴尬。

这时候new就体现出它的作用了,new来申请堆空间内部操作会分为两步:开辟堆空间+调用构造函数。但malloc只有前一步。与之关联的delete内部操作也是两步:调用析构函数+释放堆空间。free只有后一步。

这里好像还不太理解,下面用栈这个类来举例:

#include<iostream>
using namespace std;
class Stack
{
public:
	Stack(int n=4)
	{
		cout << "Stack()" << endl;
		p = new int[n];
		top = 0;
		capcity = n;
	}

	~Stack()
	{
		cout << "~A()" << endl;
		delete[] p;
		top = capcity = 0;
	}
private:
	int* p;
	int top;
	int capcity;
};
int main()
{
	Stack* ps = (Stack*)malloc(sizeof(Stack));
	free(ps);
	return 0;
}

代码运行结果:

eb2f54b3e07d489a91e9ad590b44a3d6.png

由此可见,malloc申请堆空间时,没有调用构造函数,free时也没有调用析构函数。

此时内存分布如下:

c5ecfb42b4ca419cb8f109ec3a444121.png

此时,由于用malloc只会为成员变量开空间,不会调用构造函数,就没法初始化p指针、top、capcity。栈也就失去了作用。若用new来申请堆空间:

int main()
{
	Stack* ps = new Stack;
	delete ps;
	return 0;
}

运行结果:

7ba80904c28d4aa4ae4d4325b99b7d8f.png

由此可见,用new申请堆空间时,调用了构造函数,delete时也调用了析构函数。

此时内存分布如下:

49d0e81675f04a2689341d20e26adaed.png由于用new先为成员变量开空间,再调用构造函数,就会初始化p指针(指向一片堆空间),top、capcity也不是随机值了。这才是一个正确的栈。 

delete时,也会先调用析构,再释放成员变量在堆上的空间。

eb70e10af4c349febd46d30be91b3b23.png


由上面这个示例可以感受到new与delete存在的意义了吧! 

2.new与delete基础语法

 

逐个介绍:

new一个内置类型对象

//内置类型
int* p1 = new int;
delete p1;
//自定义类型
Stack* ps=new Stack;
delete ps;

new一个内置类型对象并初始化它

int* p2 = new int(3);//将*p2初始化为3
delete p2;
//自定义类型
Stack* ps=new Stack(2);//调用非默认构造函数
delete ps;

 new多个内置类型对象( delete[] 来释放空间)

int* p3 = new int[10];//一口气new十个
delete[] p3;
//自定义类型
Stack* ps=new Stack[5];//一口气五个对象
delete[] ps;

new多个内置类型对象并依次初始化( delete[] 来释放空间)

int* p4 = new int[10] {1, 2, 3};//依次初始化,没写的初始化为0
delete[] p4;
//自定义类型
Stack* ps = new Stack[5]{ 1,2 };//一口气new五个对象,并分别调用构造函数
delete[] ps;

3.(malloc、free)与(new、delete)的区别(面试高频)

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在释放空间前会调用析构函数完成空间中资源的清理

今天的内容就分享到这里啦,如果对大家有所帮助,记得点赞收藏不迷路。订阅下方的C++专栏。会持续爆肝C++实用知识!

 

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

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

相关文章

百度秋招攻略,百度网申笔试面试详解

百度秋招简介 作为行业巨头&#xff0c;百度向社会提供的岗位一直都是非常吃香的&#xff0c;每年也都有很多考生密切关注&#xff0c;百度发布的招聘广告&#xff0c;以尽可能的让自己进入这家企业工作&#xff0c;实现自己的人生价值。那么百度每年的秋招时间是多久&#xf…

An unexpected error has occurred. Conda has prepared the above report

今日在服务器上创建anaconda虚拟环境的时候&#xff0c;出现了如下报错 An unexpected error has occurred. Conda has prepared the above report 直接上解决方案 在终端中输入如下指令 conda config --show-sources 如果出现以下提示&#xff0c;说明多了一个文件 输入以下…

JVM 性能优化思路

点击下方关注我&#xff0c;然后右上角点击...“设为星标”&#xff0c;就能第一时间收到更新推送啦~~~ 一般在系统出现问题的时候&#xff0c;我们会考虑对 JVM 进行性能优化。优化思路就是根据问题的情况&#xff0c;结合工具进行问题排查&#xff0c;针对排查出来的可能问题…

[Docker精进篇] 详细配置和部署镜像(一) 文末送书

前言&#xff1a; 容器提供了将应用程序的代码、运行时、系统工具、系统库和配置打包到一个实例中的标准方法。 文章目录 一. 认识Docker1️⃣docker服务端2️⃣docker客户端3️⃣docker仓库 二. 使用Docker1️⃣卸载旧的2️⃣安装 yum-utils3️⃣添加阿里云镜像&#xff1a;4️…

使用Java 8 中的 Stream 遍历树形结构

1 前言 可能平常会遇到一些需求&#xff0c;比如构建菜单&#xff0c;构建树形结构&#xff0c;数据库一般就使用父id来表示&#xff0c;为了降低数据库的查询压力&#xff0c;我们可以使用Java8中的Stream流一次性把数据查出来&#xff0c;然后通过流式处理&#xff0c;我们一…

安卓应用面试

Cordova 说明&#xff1a;一个移动框架&#xff0c;将HTML&#xff0c;CSS&#xff0c;JS封装为原生APP(hybird) 优点&#xff1a;跨平台&#xff0c;利于移植&#xff0c;能利用HTML5的各种特性&#xff0c;快速开发&#xff0c;成本低 缺点&#xff1a;不能使用设备的所以…

0基础学习VR全景平台篇 第83篇:智慧眼-怎么理解分类?

一、功能说明 分类可以理解为&#xff0c;为了方便城市运营工作的管理所实行的行政区划&#xff0c;如XXX乡镇、XXX街道等等。 二、后台编辑界面 1、点击【新增】&#xff0c;填写分类的名称&#xff0c;若有上一级分类&#xff0c;那么还需选择父级分类&#xff0c;建议从最…

容灾备份服务器怎么样?

容灾备份服务器是一种用于保护信息系统的设备&#xff0c;它可以在系统出现故障时提供备用服务。容灾备份服务器通常包括两个部分&#xff1a;容灾和备份。容灾是指在遭遇灾害时能保证信息系统能正常运行&#xff0c;帮助企业实现业务连续性的目标。备份是为了应对灾难来临时造…

Mysql数据库之单表查询

目录 一、练习时先导入数据如下&#xff1a; 二、查询验证导入是否成功 三、单表查询 四、where和having的区别 一、练习时先导入数据如下&#xff1a; 素材&#xff1a; 表名&#xff1a;worker-- 表中字段均为中文&#xff0c;比如 部门号 工资 职工号 参加工作 等 CRE…

【python 深度学习】解决遇到的问题

目录 一、RuntimeError: module compiled against API version 0xc but this version of numpy is 0xb 二、AttributeError: module ‘tensorflow’ has no attribute ‘flags’ 三、conda 更新 Please update conda by running 四、to search for alternate channels that…

原型链污染

文章目录 1. javascript 原型链2. 原型链变量的搜索3. prototype 原型链污染4. 原型链污染例题4.1 题1&#xff1a;4.2.题2&#xff1a; 1. javascript 原型链 js在ECS6之前没有类的概念&#xff0c;之前的类都是用funtion来声明的。如下 可以看到b在实例化为test对象以后&…

【Linux】用户和权限

文章目录 前言什么是 root 用户su 命令和 exit 命令sudo 命令为普通用户配置 sudo 认证 用户、用户组管理什么是Linux 用户和用户组用户组管理用户管理创建用户删除用户查看用户所属组将指定用户添加到指定用户组中 查看当前系统的用户和用户组 权限控制权限信息 修改权限控制修…

【IDEA问题】下载不了源代码

引出问题 最近不知道怎么打开 IDEA&#xff0c;本想查看源代码&#xff0c;然后点击下载源码&#xff0c;总是报找不到此对象的源代码。百度找了半天&#xff0c;GPT问了半天还是解决不了&#xff0c;直到遇到了这篇&#xff1a;idea中无法下载源码问题解决&#xff0c;终于得…

74、75、76——tomcat项目实战

tomcat项目实战 tomcat 依赖 java运行环境,必须要有jre , 选择 jdk1.8 JvmPertest 千万不能用 kyj易捷支付 项目机器 选择 一台机器 ,安装jdk1.8的机器下载tomcat的包 上传到机器,解压tomcattomcat文件 bin文件夹: 启动文件 堆栈配置文件 catalina.sh JAVA_OPTS="-Xm…

Nginx反向代理配置+负载均衡集群部署

文章目录 负载均衡反向代理基础环境部署&#xff1a;什么是代理实验环境图流量过程 环境部署准备两台Web服务器安装Nginx准备页面内容添加主机名 代理服务器配置 修改windos hosts文件测试&#xff1a;终端浏览器 负载均衡反向代理基础环境部署&#xff1a; 什么是代理 正向代…

腾讯云轻量应用服务器CPU型号?处理器主频多少?

腾讯云轻量应用服务器CPU型号是什么&#xff1f;处理器主频多少&#xff1f;轻量应用服务器不支持指定CPU处理器型号&#xff0c;目前腾讯云服务器网账号下的轻量应用服务器&#xff0c;CPU采用2.5GHz主频的Intel(R) Xeon(R) Gold 6133 处理器&#xff0c;睿频 3.0GHz&#xff…

160. 相交链表 题解

题目描述&#xff1a;160. 相交链表 - 力扣&#xff08;LeetCode&#xff09; 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&#xff0c;返回 null 。 注&#xff1a;本题中链表相交是“Y”型的&am…

ClickHouse(十三):Clickhouse MergeTree系列表引擎 - ReplicingMergeTree

进入正文前&#xff0c;感谢宝子们订阅专题、点赞、评论、收藏&#xff01;关注IT贫道&#xff0c;获取高质量博客内容&#xff01; &#x1f3e1;个人主页&#xff1a;含各种IT体系技术&#xff0c;IT贫道_Apache Doris,大数据OLAP体系技术栈,Kerberos安全认证-CSDN博客 &…

unity海康威视原生SDK拉取网络摄像头画面,并展示在一个Material上

原理是使用sdk获取视频流&#xff0c;格式为YUV&#xff0c;然后分离YUV通道到三张不同的Texture2D上&#xff0c;通过shader将三个通道重新输出为原始图像。 我将所用的各个部分已经整理成一个压缩包&#xff0c;免积分下载 压缩包结构如下 使用步骤 1 DLL:放在Plugins文件…

wordpress数据表中标签和分类如何区分?

wordpress中标签和分类是什么关系怎么区分&#xff1f;最后有一个群的网友告诉了我文章ID和标签ID的关系是放在了wp_term_relationships表中&#xff0c;然后我百度了下这个表的结构和相关介绍&#xff0c;发现果然如此&#xff0c;先把文章保存起来&#xff1a; wp_term_rela…