【C++学习手札】new和delete看这一篇就够了!

                                         食用指南:本文在有C基础的情况下食用更佳   

                                       🍀本文前置知识: C++类 

                                       ♈️今日夜电波: Prover—milet

                                                                1:21 ━━━━━━️💟──────── 4:01
                                                                    🔄   ◀️   ⏸   ▶️    ☰ 

                                      💗关注👍点赞🙌收藏您的每一次鼓励都是对我莫大的支持😍 


目录

🌞引入—从C语言malloc、free到C++new、delete

🌔 一、new和delete语法定义

        new的语法定义

        delete的语法定义

        new的初始化

🌕二、给类对象申请空间(为什么说C++中要用new和delete)

        用malloc和用new给类申请空间的区别

         new申请对象数组

🌖三、一些注意事项

        delete void*可能会出错

        特别注意:malloc、free和new、delete 不可以混搭使用!

        使用 new 和 delete 采用相同形式


🌞引入—从C语言malloc、free到C++new、delete

        各位请先看下面这段代码:

void test1()//C语言动态管理空间
{int* p = NULL;p = (int*)malloc(sizeof(int));*p = 100;printf("%d\n", *p);free(p);
}void test2()//C++动态管理空间
{int* p = NULL;p = new int(100);printf("%d\n", *p);delete p;
}

        这两段代码实现的功能是一样的。通过观察以及比对,我们很容易就能发现malloc和free分别对应着new和delete。乍一看,malloc、free和new、delete好像没什么区别?没错,他们的功能都是一样的,都是用来动态管理空间的。但是,如果细细观察,你会发现他们区别可大了!

         注意:

                1、new不需要强制类型转换。

                2、new可以在开辟空间时,可以同时初始化空间内容。

         \(^o^)/~ok,基本的引入就到这吧,现在我们进入正题,对于new、delete详解~


🌔 一、new和delete语法定义

        new的语法定义

//动态分配一个空间时
指针 = new 指针对应的类型;//例1
int* ptr = new int;//在堆上分配一个整数的内存,并将其地址存储在指针ptr中//申请多个空间时或者用于动态分配数组的内存时
指针 = new 指针对应的类型[申请的大小];//例2int* arr = new int[5];//在堆上分配一个包含5个整数的数组,并将其起始地址存储在指针arr中

        delete的语法定义

//当只开辟了一个空间时delete 所要释放开间的指针//例1
delete ptr;//释放空间//申请多个空间时或者用于动态分配数组的内存时delete 所要释放开间的指针delete[] 所要释放空间的指针 //此释放该指针开辟的所有空间//例2delete arr;//可能只释放首个空间->不同编译器所为不同
delete[] arr;//全部释放

        特别注意:如果new和delete应当采用相同形式,详见本文末。

        new的初始化

//动态分配一个空间时
指针 = new 指针对应的类型(对应类型数值);//例1
int* ptr = new int(100)//初始化空间值为100//申请多个空间时或者用于动态分配数组的内存时
指针 = new 指针对应的类型[申请的大小]{数值(用,隔空)};//例2
int* arr = new int[5]{1,2,3,4,5};//初始化5个空间值依次为1,2,3,4,5

        栗子:

void test2()//C++动态管理空间
{int* p = NULL;p = new int(100);printf("%d\n", *p);delete p;int* q = NULL;int* z = NULL;q = new int[5] {10, 20, 30, 40, 50};z = new int[5] {0};for (int i = 0; i < 5; i++){cout << q[i] << " ";}cout << endl;for (int i = 0; i < 5; i++){cout << z[i] << " ";}delete[]z;delete[]q;
}

🌕二、给类对象申请空间(为什么说C++中要用new和delete)

        用malloc和用new给类申请空间的区别

        请看下面这段代码~

class A
{
public:int num;public:A(){num = 200;cout << "构造函数" << endl;}~A(){cout << "析构函数" << endl;}
};void test()
{A* p = (A*)malloc(sizeof(A));p->num = 100;cout << "malloc:num=" << p->num << endl;free(p);cout << endl;A* q = new A;cout << "new:num=" << q->num << endl;delete q;
}

        以下为该段代码的结果:

        很明显的能看到,如果我们使用malloc开辟空间以及free来释放空间,类中最经典的构造函数和析构函数都是没有被调用的!然而,使用new来申请空间 如果申请成功 就会自动调用 对应类的构造函数,在用delete释放空间时会自动调用析构函数!因此,在C++中,我们使用new和delete会比malloc和free安全的多!

         new申请对象数组

         请看下面这段代码~

class A
{
public:int num;public:A(){num = 100;cout << "无参构造函数num="<<num << endl;}A(int n){num = n;cout << "有参构造函数num="<<num << endl;}~A(){cout << "析构函数num="<<num << endl;}
};void test()
{cout << "无参:" << endl;A* arr1 = new A[5];delete[]arr1;cout << endl;cout << "有参:" << endl;A* arr2 = new A[5]{A(1),A(2),A(3),A(4),A(5)};delete[] arr2;
}

          以下为该段代码的结果: 

         以上的代码分别为利用无参构造函数和有参构造函数构造的对象数组,从以上例子我们也可总结出以下几点要点:

        1、类对象数组本质是数组 只是数组的每个元素是类的对象。

        2、如果想让对象数组中的元素调用有参构造 必须人为使用 有参构造初始化。
        3、初始化的元素 调用有参构造 没有初始化的 调用无参构造。

        4、当创建一个对象数组的时候, 必须对数组中的每一个对象调用构造函数, 除了在栈
        上可以聚合初始化, 必须提供一个默认的构造函数。

        这里建议回顾回顾类的知识:  构造函数与析构函数 (这是链接,快点!)

在对象数组中:

        每个元素自动调用构造和析构函数,而他的构造顺序和析构顺序入下图所示:

         构造按照入上文例子中有参构造,从左往右,也就是说谁先定义谁先构造,而析构则是相反,谁最后定义谁最先析构!


🌖三、一些注意事项

        delete void*可能会出错

        如果对一个 void*指针执行 delete 操作, 这将可能成为一个程序错误, 除非指针指
向的内容是非常简单的, 因为它将不执行析构函数.以下代码未调用析构函数, 导致可用内存减少。
所以尽量不要用delete释放void *!

           栗子:

class Person {
public:Person(char* name, int age) {pName = (char*)malloc(sizeof(name));strcpy(pName, name);mAge = age;}~Person() {if (pName != NULL) {delete pName;}}
public:char* pName;int mAge;
};
void test() {char arr[] = "john";void* A = new Person(arr, 22);delete A;
}

 特别注意:malloc、free和new、delete 不可以混搭使用!

        使用 new 和 delete 采用相同形式

        请仔细看下面这段代码~

    Person* person = new Person[10];delete person;

        以上代码有什么问题吗?
        这里使用了两个编译器来对该代码进行运行,分别出现了以下错误:vs 下直接中断、 qt 下析构函数调用一次
        使用了 new 也搭配使用了 delete, 问题在于 Person 有 10 个对象, 那么其他 9 个对象可能没有调用析构函数, 也就是说其他 9 个对象可能删除不完全, 因为它们的析构函数没有被调用。 我们现在清楚使用 new 的时候发生了两件事: 一、 分配内存; 二、 调用构造函数, 那么调用 delete 的时候也有两件事: 一、 析构函数; 二、 释放内存。 那么刚才我们那段代码最大的问题在于: person 指针指向的内存中到底有多少个对象, 因为这个决定应该有多少个析构函数应该被调用。 换句话说, person指针指向的是一个单一的对象还是一个数组对象, 由于单一对象和数组对象的内存布局是不同的。 更明确的说, 数组所用的内存通常还包括“数组大小记录”, 使delete 的时候知道应该调用几次析构函数。 单一对象的话就没有这个记录。

        单一对象和数组对象的内存布局可理解为下图:

        本图只是为了说明, 编译器不一定如此实现, 但是很多编译器是这样做的。 当我们使用一个 delete 的时候, 我们必须让 delete 知道指针指向的内存空间中是否存在一个“数组大小记录”的办法就是我们告诉它。 当我们使用 delete[ ], 那么 delete就知道是一个对象数组, 从而清楚应该调用几次析构函数。 结论: 如果在 new 表达式中使用[ ], 必须在相应的

delete 表达式中也使用[ ].如果在 new 表达式中不使用[], 一定不要在相应的 delete 表达式

中使用 [ ]。


                   感谢你耐心的看到这里ღ( ´・ᴗ・` )比心,如有哪里有错误请踢一脚作者o(╥﹏╥)o! 

                                        

                                                                        给个三连再走嘛~   ​​​​​​​  

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

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

相关文章

安卓如何卸载应用

卸载系统应用 首先需要打开手机的开发者选项&#xff0c;启动usb调试。 第二步需要在电脑上安装adb命令&#xff0c;喜欢的话还可以将它加入系统path。如果不知道怎么安装&#xff0c;可以从这里下载免安装版本。 第三步将手机与电脑用数据线连接&#xff0c;注意是数据线&a…

Linux mysql5.7开启 binlog

查看 mysql是否开启 binlog。 查看命令&#xff1a; show variables like %log_bin%; log_bin OFF 是关闭的状态。 编辑my.cnf配置文件 vim /etc/my.cnf 默认的配置文件内容&#xff1a; 增加下面内容 server_id 1 binlog_format ROW log-bin mysql_log_bin 重启mysq…

C++友元函数和友元类的使用

1.友元介绍 在C中&#xff0c;友元&#xff08;friend&#xff09;是一种机制&#xff0c;允许某个类或函数访问其他类的私有成员。通过友元&#xff0c;可以授予其他类或函数对该类的私有成员的访问权限。友元关系在一些特定的情况下很有用&#xff0c;例如在类之间共享数据或…

pdf怎么删除不要的页面?这几种删除方法了解一下

pdf怎么删除不要的页面&#xff1f;在处理pdf文档时&#xff0c;我们经常会遇到需要删除某些页面的情况。一些多余或无关的页面可能会对文档的整体结构造成混乱&#xff0c;甚至会影响文档的可读性。此外&#xff0c;删除多余页面还可以减小文件大小&#xff0c;方便存储和传输…

每天五分钟机器学习:梯度下降算法和正规方程的比较

本文重点 梯度下降算法和正规方程是两种常用的机器学习算法,用于求解线性回归问题。它们各自有一些优点和缺点,下面将分别对它们进行详细的讨论。 区别 1. 梯度下降算法是一种迭代的优化算法,通过不断迭代调整参数来逼近最优解。它的基本思想是根据目标函数的梯度方向,沿…

springboot房地产管理java购房租房二手房j客户sp源代码mysql

本项目为前几天收费帮学妹做的一个项目&#xff0c;Java EE JSP项目&#xff0c;在工作环境中基本使用不到&#xff0c;但是很多学校把这个当作编程入门的项目来做&#xff0c;故分享出本项目供初学者参考。 一、项目描述 springboot房地产管理 系统1权限&#xff1a;管理员 …

基于SLAM的规划算法仿真复现|SLAM|智能规划

图片来自百度百科 前言 那么这里博主先安利一些干货满满的专栏了&#xff01; 首先是博主的高质量博客的汇总&#xff0c;这个专栏里面的博客&#xff0c;都是博主最最用心写的一部分&#xff0c;干货满满&#xff0c;希望对大家有帮助。 高质量博客汇总https://blog.csdn.n…

go-zero 是如何实现令牌桶限流的?

原文链接&#xff1a; 上一篇文章介绍了 如何实现计数器限流&#xff1f;主要有两种实现方式&#xff0c;分别是固定窗口和滑动窗口&#xff0c;并且分析了 go-zero 采用固定窗口方式实现的源码。 但是采用固定窗口实现的限流器会有两个问题&#xff1a; 会出现请求量超出限…

Apoll 多项式规划求解

一、纵向规划 void QuarticPolynomialCurve1d::ComputeCoefficients(const float x0, const float dx0, const float ddx0, const float dx1,const float ddx1, const float p) {if (p < 0.0) {std::cout << "p should be greater than 0 at line 140." &…

MySQL中基础查询语句

用户表user数据如下&#xff1a; iddevice_idgenderageuniversityprovince12138male21北京大学Beijing23214male复旦大学Shanghai36543famale20北京大学Deijing42315female 23 浙江大学ZheJiang55432male25山东大学Shandong 1&#xff0c;写出ddl语句创建如上表&#xff0c;…

解密Redis:应对面试中的缓存相关问题2

面试官&#xff1a;Redis集群有哪些方案&#xff0c;知道嘛&#xff1f; 候选人&#xff1a;嗯~~&#xff0c;在Redis中提供的集群方案总共有三种&#xff1a;主从复制、哨兵模式、Redis分片集群。 面试官&#xff1a;那你来介绍一下主从同步。 候选人&#xff1a;嗯&#xff…

设计模式行为型——模板模式

目录 模板模式的定义 模板模式的实现 模板模式角色 模板模式类图 模板模式举例 模板模式代码实现 模板模式的特点 优点 缺点 使用场景 注意事项 实际应用 模板模式的定义 模板模式&#xff08;Template Pattern&#xff09;属于行为型设计模式&#xff0c;又叫模版…

第7章 通过内网本机IP获取微信code值及其对code值的回调。

在第5章中讲述了怎样通过内网穿透外外网从而获取微信code值&#xff0c;实际上微信测试帐号管理页中也支持通过内网本机IP获取微信code值。 1 重构launchSettings.json "https": { "commandName": "Project", "dotnetRunMessages": t…

数据结构——空间复杂度

3.空间复杂度 空间复杂度也是一个数学表达式&#xff0c;是对一个算法在运行过程中临时占用存储空间大小的量度 。 空间复杂度不是程序占用了多少bytes的空间&#xff0c;因为这个也没太大意义&#xff0c;所以空间复杂度算的是变量的个数。 空间复杂度计算规则基本跟实践复杂…

kafka partition的数据文件(offffset,MessageSize,data)

partition中的每条Message包含了以下三个属性&#xff1a; offset&#xff0c;MessageSize&#xff0c;data&#xff0c;其中offset表示Message在这个partition中的偏移量&#xff0c;offset不是该Message在partition数据文件中的实际存储位置&#xff0c;而是逻辑上一个值&…

【刻削生千变,丹青图“万相”】阿里云AI绘画创作模型 “通义万相”测评

刻削生千变&#xff0c;丹青图“万相 4月7日&#xff0c;阿里大模型“通义千问”开始邀请用户测试体验。现阶段该模型主要定向邀请企业用户进行体验测试&#xff0c;用户可通过官网申请&#xff08;tongyi.aliyun.com&#xff09;&#xff0c;符合条件的用户可参与体验。 随…

RabbitMQ(一) - 基本结构、SpringBoot整合RabbitMQ、工作队列、发布订阅、直接、主题交换机模式

RabbitMQ结构 Publisher &#xff1a; 生产者 Queue: 存储消息的容器队列&#xff1b; Consumer:消费者 Connection&#xff1a;消费者与消息服务的TCP连接 Channel:信道&#xff0c;是TCP里面的虚拟连接。例如&#xff1a;电缆相当于TCP&#xff0c;信道是一条独立光纤束&…

在vue中Antv G2 折线图如何添加点击事件获取折线上点的值

在项目中有个需求是点击折线图的点&#xff0c;获取当前点的信息&#xff0c;其它图形都可以参考相关的API获取到&#xff0c;但area做的折线图怎么都获取不到点击的信息&#xff0c;只能获取全部的信息&#xff0c;最终解决如下&#xff1a; 实现思路 用户的鼠标在折线图上移…

基于低代码和数字孪生技术的电力运维平台设计

电力能源服务商在为用能企业提供线上服务的时候&#xff0c;不可避免要面对用能企业的各种个性化需求。如果这些需求和想法都要靠平台厂家研发人员来实现&#xff0c;那在周期、成本、效果上都将是无法满足服务运营需要的&#xff0c;这也是目前很多线上能源云平台应用效果不理…

单例模式-java实现

介绍 单例模式的意图&#xff1a;保证某个类在系统中有且仅有一个实例。 我们可以看到下面的类图&#xff1a;一般的单例的实现&#xff0c;是属性中保持着一个自己的私有静态实例引用&#xff0c;还有一个私有的构造方法&#xff0c;然后再开放一个静态的获取实例的方法给外界…