【C++】动态内存管理——new和delete

这篇文章我们讲一下C++的动态内存管理,从一个比较陌生的知识说起,我们知道,一个工程可以创建很多.c文件,我们如果定义一个全局变量,只要用extern声明一下,在每个文件都可以用。而用static修饰的全局变量只能在当前文件可用,局部的static修饰的变量只有程序走到这时才会去创建,并且只会初始化一回,比如是在一个普通函数内,就意味着如果第二次调用该函数,就不会去在初始化了。
上面所说的全局变量和static修饰的变量是存储在静态区的,我们这里所说的动态内存分配都是在堆区上的,下面说一下new和delete的基本用法,基本的形式是这样的:

int main() {
	int* p1 = new int;
	int* p2 = new int[10];
	return 0;
}

基本用法就是这样,用一个指针去接收,跟malloc是一样,但是后面会简单很多,如果就开辟一个空间的话,就直接加类型,要开辟比如十个空间就是加上方括号。那么new函数会不会初始化呢?跟malloc一样,是不会初始化的。当然我们也可以让new去初始化,就像这样:
在这里插入图片描述

单个数据初始化就用括号,多个数据就用大括号,向上面的p2情况,如果是未完全初始化,那么后面会用0给初始化,就跟数组初始化一样
在这里插入图片描述
那么想要delete也简单,直接用就行,就像这样:
在这里插入图片描述
new时用方括号了delete时就用方括号,new时不用delete时就不用
那么下面大家想一想为什么我们C++不用之前的malloc了,而是新创建了new这个操作符,对!new是一个操作符,它跟函数调用是不一样的。不只是为了简单写,还有一些其他的用处
比如说,我们有一个自定义类型,我们用malloc去创建了一个指向该类型的对象的指针,我们是很难通过这个指针去解决初始化问题的,为什么呢?首先自定义类型的成员变量是私有的,我们不能去访问,另外构造函数是程序自动调用的,我们也无法去去调用对象的构造函数,所以我说它是很难去初始化的,但也是有办法
在这里插入图片描述
但这种办法确实很鸡肋,我们这只是为了证明它可以改变。
malloc会存在这种问题,所以我们才有了new这个函数,它不仅会去开辟空间还会去调用自定义类型的构造函数
在这里插入图片描述
在这里插入图片描述
就可以这么去调用,上面是自定义类型有一个成员变量的样子,下面是有两个成员变量的样子,这就是我们上个博客写的内置类型转换。既然我们可以这么写了,那创建链表节点的时候就不用再去写相应的函数了,就可以这么去写:

struct ListNode
{
	ListNode(int val) {
		_val = val;
		_next = NULL;
	}
	int _val;
	ListNode* _next;
};

int main() {
	ListNode* n1 = new ListNode(1);
	ListNode* n2 = new ListNode(2);
	ListNode* n3 = new ListNode(3);
	return 0;
}

它直接就去自动调用构造函数了,既然new自动调用构造,那么delete就会去自动调用析构函数并且去释放空间,我们平常去析构一个比如日期类对象是没有意义的,但是当我们去建一个栈的类时调用析构就有意义了

class stack {
public:
	stack(int capacity=4) {
		 _a = new int[capacity];
		 _top = 0;
		 _capacity = capacity;
	}
	~stack() {
		delete(_a);
		_top = 0;
		_capacity = 0;
	}
private:
	int* _a;
	int _top;
	int _capacity;
};

int main() {
	stack* p = new stack;
	delete p;
	return 0;
}

这个程序呢?先是p指针指向一个栈,这个栈的12个字节是在堆区开辟的,然后会去调用堆的构造函数,又在堆上开辟4*4个字节,之后delete p时,会先去调用栈的析构函数,释放4*4个字节的空间,再去释放p指向的空间,在这里delete的作用就很明显了。
除此之外,malloc如果失败的话会去返回一个空指针,而new报错的话会抛异常,更符合C++面向对象的特性
其实我们已经知道了new的作用就是开空间和调用构造函数,那么开空间其实就用我们的malloc就可以了,只不过我们要对malloc包装一下,为了处理抛异常问题,包装完之后就变成了operator new函数,这是一个全局函数,这里的operator跟我们的运算符重载是没有关系的,只是叫这个名字而已,通过汇编我们也可以看到,new会去调用两个函数
在这里插入图片描述
我们这两个call指令就是去调用函数的意思,就是跳到对应函数的地址去执行函数,以此类推,也有一个operator delete函数,它也是去封装了free,跟new是一样的。
我们知道构造函数是不能自动调用的,但是析构函数可以,但是我们也有办法显示调用构造函数,那就是使用定位new,基本使用是这样的
在这里插入图片描述
就像第二行这样,就是这么个形式,那么显示调用有什么用处呢?比如说,我们可能有时候会频繁的小规模的开辟空间,而开辟空间这个过程是比较效率低的,这是我们就可以先申请一大块空间,叫做内存池,这就留着用,这时去内存池要空间就不用开辟但是得初始化,这时我们的显式调用构造函数就派上用场了。

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

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

相关文章

SpringBoot面试题:(一)SpringBoot自动装配原理源码解析

源码研究 SpringBoot启动类:SpringBootApplication注解 import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;SpringBootApplication public class SpringBoot1Application {public static …

项目文章|冰川宏病毒功能多样性新进展

近期,凌恩生物客户兰州大学泛第三极环境中心合作的研究论文“Diversity and function of mountain and polar supraglacial DNA viruses”发表在《Science Bulletin》(IF 18.9)。该研究结果首次系统地描述了极地冰川上DNA病毒的多样性、功能和…

【2】PyQt创建窗口

1. 第一个PyQt窗口 from PyQt5.QtWidgets import QApplication,QWidget import sys# 1.创建应用程序 app QApplication(sys.argv)# 2.创建窗口 w QWidget()# 3.显示窗口 w.show()# 4.等待窗口停止 sys.exit(app.exec()) 执行代码,就会显示PyQt窗口: 2. PyQt模块简介 PyQt中…

kubectl获取命名空间下所有configmap集合的方法

前言: 获取单个configmap并忽略特定字段的操作可参照:kubectl获取ConfigMap导出YAML时如何忽略某些字段。 要获取命名空间下所有ConfigMap并忽略特定字段,你可以使用kubectl命令与例如yq这样的工具结合使用来忽略或删除不需要的字段。以下是…

数据分享 I 各类制造业企业进入数量数据,shp/excel格式数据,覆盖2002-2019年数据,已可视化处理

随着经济的发展和社会的进步,制造业作为国民经济的重要支柱,一直保持着快速的发展态势。近年来,随着国家对制造业的大力扶持,各类制造业企业如雨后春笋般涌现出来,为经济的发展注入了新的活力。 各类制造业企业进入…

公有云迁移研究——AWS DMS

大纲 1 什么是DMS2 DMS的作用3 DMS在迁移的时候都做些什么4 在使用DMS的时候我们需要做些什么5 操作5.1 创建两个数据库终端节点5.2 创建迁移任务 6 可能遇到的问题7 总结 在本地机房或其他云往AWS上做迁移时,往往会遇到数据库迁移的任务。如果数据量不是特别大&…

widnows 使用cprofile、gprof2dot、graphviz对python项目进行可视化性能分析

1. 运行cprofile生成python方法调用信息 pr cProfile.Profile() pr.enable() # 开始记录# 要执行的代码 res your_method()pr.disable() # 结束记录 pr.dump_stats(your/path/restats.dump) #写入dump文件 pr.print_stats() #打印 2. 安装gprof2dot和graphviz 2.1 安装gpr…

十年数据分析师告诉你,这款国产数据分析工具真的很好用!

今天早上上班的时候经过一同事,看见他正苦大仇深的做着数据分析报告,老李走上前一问才知道,他的EXCEL又双叒罢工了。   数据分析师的核心能力是思维,而次核心能力就是工具。如古人云打仗需要一把趁手的兵器。对于初入行业的数据分…

数据结构-带头双向循环链表

文章目录 一.头结点二.双链表1双链表的概念与结构2.与单链表相比 三.循环链表1.关于循环链表2.循环链表的优点 四.带头双向循环链表1.带头双向循环链表2.结构图3.实现 五.代码一览 一.头结点 在链表中设置头结点的作用是什么 标识链表:头结点是链表的特殊节点,它的存在能够明确…

JS初步了解this

什么是环境对象? 环境对象:指的是函数内部特殊的变量this,它代表着当前函数运行时所处的环境 作用:弄清楚this的指向,可以让我们代码更简洁 在普通函数中: // 每个函数里面都有this 普通函数的this指向wind…

rcssci包横空出世,限制性立方样条全自动切点靓图

z致敬前辈:R语言统计与绘图 仅以本篇2800字真文一并纪念工作11年来潦倒的收入、间歇的鸡血、憋屈的倔强、幽暗的过往和心中的远方。 1 缘起 Restricted cubic splines (RCS)近年来火遍各类SCI期刊,初次接触的小伙伴们可以去搜索笔者前期的2篇RCS文章补充一下基础知…

6.5 Windows驱动开发:内核枚举PspCidTable句柄表

在 Windows 操作系统内核中,PspCidTable 通常是与进程(Process)管理相关的数据结构之一。它与进程的标识和管理有关,每个进程都有一个唯一的标识符,称为进程 ID(PID)。与之相关的是客户端 ID&am…

(C语言)求出1,2,5三个数不同个数组合为100的组合个数

#include<stdio.h> int main() {int count;for(int i 0;i < 100;i )for(int j 0;j < 50;j )for(int k 0;k < 20;k ){if(i j*2 k*5 100){count;printf("100可以拆分为%d个1元&#xff0c;%d个2元&#xff0c;%d个5元\n",i,j,k);} }printf("…

2023年度端侧transformer类分类力作SwiftFormer模型解读

写在前面&#xff1a;本篇直接结合代码来理解网络的笔记 paper: Swiftformer-paper code: https://github.com/Amshaker/SwiftFormer 文章目录 网络结构精析零、整体一、patch embed二、stage 网络结构精析 零、整体 可以看到结构中&#xff0c;整体就是&#xff1a; stem -&…

洗地机哪个牌子好用?洗地机希亦、石头、添可、西屋谁的清洁力更强?

洗地机的出现极大地改善了清洁过程&#xff0c;提高了效率&#xff0c;减少了人力投入。但随着市场上洗地机的种类和功能不断增加&#xff0c;人们可能会感到困惑&#xff0c;不知道如何选择适合自己需求的机器。为了帮助消费者更好地了解洗地机的选择&#xff0c;今天我将带大…

从Intel Cyclone10GX TransceiverPHY 高速收发器认识ATX PLL、FPLL、CMU PLL等PLL

文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 前言 在使用Intel Cyclone10GX TransceiverPHY的过程中发现这个IP还是比较复杂的&#xff0c;特别是时钟系统&#xff0c;提到了多种PLL:ATX PLL、FPLL、CMU PLL&#xff0c;这里进行一下扩展学…

vue3项目打包发布到apache服务器的流程

vue3项目打包发布到apache服务器的流程&#xff08;不包含开机自启动apache&#xff09; 1. 下载部署apache服务器 打开apache官网https://www.apachelounge.com/download/ 下载windows的apache版本。 2. 在本地的E盘新建一个文件http&#xff0c;把下载好的apache解压放进…

时间选择器

<el-form-item label"时间范围"><!-- <el-date-picker size"small"v-model"createTime"type"daterange"range-separator"至"start-placeholder"请输入起始创建时间"end-placeholder"请输入终止创…

【C语言:自定义类型(结构体、位段、共用体、枚举)】

文章目录 1.结构体1.1什么是结构体1.2结构体类型声明1.3结构体变量的定义和初始化1.4结构体的访问 2.结构体对齐2.1如何对齐2.2为什么存在内存对齐&#xff1f; 3.结构体实现位段3.1什么是位段3.2位段的内存分配3.3位段的跨平台问题3.4位段的应用3.5位段使用注意事项 4.联合体4…

vmware ubuntu22 访问github

1.虚拟机选NAT模式。 2.firefox找到下图setting。 3.选第四个&#xff0c;填主机ip和局域网代理的端口号。 4. 此时你应该能访问github了。