【C++】new 和 delete

news2024/11/27 15:37:08

目录

一 引言

二 new

三 delete

四 new和delete操作自定义类型

五 operator new与operator delete函数

六  new和delete的实现原理

1 内置类型

2 自定义类型

1 new的原理

2 delete的原理

3 new T[N]的原理

4 delete[]的原理

七  定位new表达式(placement-new)

八 细节


一 引言

C语言内存管理方式在C++中可以继续使用,但有些地方就无能为力,而且使用起来比较麻烦,因 此C++又提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理。

二 new

int main()
{
       // 动态申请一个int类型的空间
       int* p1 = new int;

       // 动态申请一个int类型的空间并初始化为10
       int* p2 = new int(10);

       // 动态申请3个int类型的空间
       int* p3 = new int[3];

       //多个数据初始化
       int* p4 = new int[3]{1, 2, 3};

       return 0;
}

三 delete

int main()
{
       // 动态申请一个int类型的空间
       int* p1 = new int;

       // 动态申请一个int类型的空间并初始化为10
       int* p2 = new int(10);

       // 动态申请3个int类型的空间
       int* p3 = new int[3];

       //多个数据初始化
       int* p4 = new int[3]{1, 2, 3};

       delete p1;
       delete p2;
       delete[] p3;
       delete[] p4;


       return 0;
}

注意:申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用 new[]和delete[]

注意:匹配起来使用。

四 new和delete操作自定义类型

class A
{
public:
       A(int a = 0)
              : _a(a)
       {
              cout << "A():" << this << endl;

       }
       ~A()
       {
              cout << "~A():" << this << endl;
       }
private:
       int _a;
};


struct ListNode
{
       int _val;
       ListNode* _next;

       ListNode(int val)
              :_val(val)
              , _next(nullptr)
       {

       }
};

int main()
{
       // new/delete 和 malloc/free最大区别是 new/delete对于【自定义类型】除了开空间还会调用构造函数和析构函数
       A* p1 = (A*)malloc(sizeof(A));
       A* p2 = new A(1);
       free(p1);
       delete p2;

       // 内置类型是几乎是一样的
       A* p3 = (A*)malloc(sizeof(A) * 10);
       A* p4 = new A[10];
       free(p3);
       delete[] p4;

       //对于创建一个链表节点 我们也不像之前那些麻烦了
       ListNode* n1 = new ListNode(1);
       ListNode* n2 = new ListNode(2);
       ListNode* n3 = new ListNode(3);

       //多个对象动态内存开辟
       //方法1
       A aa1(1);
       A aa2(1);
       A aa3(1);
       A* p5 = new A[3]{ aa1, aa2, aa3 };

       //方法2
       A* p6 = new A[3]{ A(2), A(2), A(2) };

       //方法3 -->隐形类型转换
       A* p7 = new A[3]{ 3, 3, 3 };

       return 0;
}

malloc 不方便解决动态申请的自定义类型对象的初始化问题

注意:在申请自定义类型的空间时,new会调用构造函数,delete会调用析构函数,而malloc与 free不会

new :  step1--> 申请对象空间  step2-->调用构造函数

delete: step1--> 调用析构函数   step2--> 释放对象空间

五 operator new与operator delete函数

new和delete是用户进行动态内存申请和释放的操作符

operator new 和operator delete是 系统提供的全局函数

new在底层调用operator new全局函数来申请空间

delete在底层通过 operator delete全局函数来释放空间。

class Stack
{
public:
       Stack(int capacity = 4)
       {
              cout << "Stack(int capacity = 4)" << endl;

              _a = new int[capacity];
              _top = 0;
              _capacity = capacity;
       }

       ~Stack()
       {
              cout << "~Stack()" << endl;

              delete[] _a;
              _a = nullptr;
              _top = 0;
              _capacity = 0;
       }
private:
       int* _a;
       int  _top;
       int  _capacity;
};

int main()
{
       
       Stack* p1 = new Stack;
       delete p1;

       Stack* p2 = (Stack*)operator new(sizeof(Stack));
       operator delete(p2);

       
       // new/delete  new[]/delete[]  malloc/free
       // 一定要配对使用,否则结果是未定义

       return 0;
}

operator new 和 operator delete库里面的全局函数,封装了malloc 和 free

new : step1--> 申请对象空间 step2-->调用构造函数

step1 为什么不能用malloc 因为malloc 申请空间返回0 但是面向对象是不能接收返回值的  所以创建了operator new 来处理(抛异常)

而operator delete 纯粹是为了和operator new搭对'

六  new和delete的实现原理

1 内置类型

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

2 自定义类型

1 new的原理

1. 调用operator new函数申请空间

2. 在申请的空间上执行构造函数,完成对象的构造

2 delete的原理

1. 在空间上执行析构函数,完成对象中资源的清理工作

2. 调用operator delete函数释放对象的空间

3 new T[N]的原理

1. 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对象空间的申请

2. 在申请的空间上执行N次构造函数

4 delete[]的原理

1. 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理

2. 调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释放空间

那我们现在可以解释我们为啥要配对使用

 

七  定位new表达式(placement-new)

定位new表达式是在已分配的原始内存空间中调用构造函数初始化一个对象。

使用格式:

new (place_address) type或者new(place_address) type(initializer - list)

place_address必须是一个指针,initializer - list是类型的初始化列表

使用场景:

定位new表达式在实际中一般是配合内存池使用。因为内存池分配出的内存没有初始化,所以如

果是自定义类型的对象,需要使用new的定义表达式进行显示调构造函数进行初始化。

class A
{
public:
       A(int a = 0)
              : _a(a)
       {
              cout << "A():" << this << endl;
       }

       ~A()
       {
              cout << "~A():" << this << endl;
       }

private:
       int _a;
};


int main()
{
       // 构造函数自动调用
       A aa1;

       // A* p2 = new A(1);

       A* p1 = (A*)operator new(sizeof(A));
       // 不能这么显示调用构造函数
       //p1->A(1);
       // 但是可以用定位new显示调用构造函数
       new(p1)A(1);

       // 析构函数可以显示调用
       p1->~A();
       operator delete(p1);

       return 0;
}

八 细节

malloc/free和new/delete的区别

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

缺了好久没写博客, 主要学校的事情太忙了最近, 本节还是很容易的但是非常重要, 注重理解就好

继续加油!

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

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

相关文章

【Android Studio】各个版本下载地址

下载地址&#xff1a; https://developer.android.com/studio/archive?hlzh-cn

HashMap扩容机制详解

目录 1. 扩容的触发条件 2. 扩容的具体步骤 2.1 计算新的容量 2.2 创建新的桶数组 2.3 将元素重新分配到新的桶数组中 2.4 更新容量和阈值 3. 与并发性能的关系 4. 扩容的性能优化 5. 总结 HashMap是Java中常用的数据结构之一&#xff0c;用于存储键值对。在HashMap内…

系列十、存储引擎

一、存储引擎 1.1、概述 大家可能没有听说过存储引擎&#xff0c;但是一定听过引擎这个词&#xff0c;引擎就是发动机&#xff0c;是一个机器的核心组件。 比如&#xff0c;对于舰载机、直升机、火箭来说&#xff0c;它们都有各自的引擎&#xff0c;引擎是它们最为核心的组件。…

RHEL8_Linux_Ansible常用模块的使用

本章主要介绍Ansible中最常见模块的使用 shell模块文件管理模块软件包管理模块服务管理模块磁盘管理模块用户管理模块防火墙管理模块 ansible的基本用法如下。 ansible 机器名 -m 模块x -a "模块的参数" 对被管理机器执行不同的操作&#xff0c;只需要调用不同的模块…

Pipelined-ADC设计一:序言

现在是2023年12月18日&#xff0c;准备开新帖&#xff0c;设计一个 流水线型 模数转换器&#xff08; Pipelined-ADC &#xff09;。记录帖&#xff0c;后续会放在咸鱼。同步记录&#xff0c;谨防盗用。 初定指标&#xff1a;12位50Mhz&#xff0c;采用2.5bit每级结构&#xff…

Goland如何进行Debug断点调试

1. 进入编辑 2. 进行编辑 3. 调试运行 将鼠标移到按钮上&#xff0c;即显示其功能与快捷键 4. 常用调试快捷键 按键说明F7单步执行(进入方法)F8单步执行(不进入方法)F9继续执行

如何实现TensorFlow自定义算子?

在上一篇文章中 Embedding压缩之基于二进制码的Hash Embedding&#xff0c;提供了二进制码的tensorflow算子源码&#xff0c;那就顺便来讲下tensorflow自定义算子的完整实现过程。 前言 制作过程基于tensorflow官方的custom-op仓库以及官网教程&#xff0c;并且在Ubuntu和Mac…

算法:单链表反转

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 一、问题描述 二、栈解法Stack 三、三指针法 总结 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、问题描述 有个单链表&#xff0c;现…

【Qt之Quick模块】1. 概述及Quick应用程序创建流程

概述 Qt的Quick模块是用于创建现代化、动态和响应式用户界面的工具集。它是基于QML&#xff08;Qt Meta-Object Language&#xff09;和JavaScript的。 QML是一种声明性的语言&#xff0c;用于描述用户界面的结构和行为。它使用层叠样式表&#xff08;CSS&#xff09;的语法来…

创建型模式之简单工厂模式

一、概述 (1)简单工厂模式并不是一个标准的设计模式&#xff0c;但是它太常用了&#xff0c;简单而又神奇 (2)在简单工厂模式中用于创建实例的方法通常是静态方法&#xff0c;因此又被称为静态工厂方法模式 (3)要点&#xff1a;如果需要什么&#xff0c;只需传入一个正确的参…

鞋帽箱包品牌网站作用如何

鞋帽箱包是市场中很常见的产品&#xff0c;同时需求度又很高&#xff0c;是人们生活所需&#xff0c;除了个别高端品牌外&#xff0c;其它多数产品价格一般都比较低&#xff0c;因此很少有人会在意品牌&#xff0c;只要质量、价格、舒适度、美观好即可。 然而对企业来讲&#…

滑动窗口(一)

滑动窗口 什么是滑动窗口算法&#xff1f;通俗的来讲就是 “同向双指针” &#xff0c;当一组数据的规律含有单调性的时候&#xff0c;就可以使用下面这套逻辑来优化暴力解法。 当两个指针同向移动的时候&#xff0c;类似于一个窗口在滑动。使用于在连续序列里找特殊的子串、…

计算机网络基础——网线认识与制作,线缆类型、线序、端接标准及注意事项

一、引言 网线制作是网络基础知识中不可或缺的。网络传输过程中&#xff0c;网线的质量和制作方法都会直接影响传输的速度和稳定性。本文将详细介绍网线制作的基础知识、线缆类型、线序、端接标准及注意事项。希望通过本文&#xff0c;读者能够更好地了解和掌握网线制作的方法…

PIG框架学习1——密码模式登录认证获取Token流程

文章目录 O、前言一、总流程概括&#xff1a;二、具体流程分析PIG提供的具体流程图&#xff1a;鉴权请求报文示例0、网关前置处理1、客户端认证处理2、正式接受登录请求3、组装认证对象4、认证管理器进行认证&#xff08;授权认证调用&#xff09;5、认证成功处理器 O、前言 对…

5G/4G工业无线通信模块:实现智能制造的关键利器

工业无线通信模块&#xff0c;作为实现智能制造的关键利器&#xff0c;正在推动着工业界的变革与创新。随着信息技术的快速发展和工业自动化的不断深入&#xff0c;工业无线通信模块正逐渐成为工业生产中不可或缺的重要组成部分。它不仅在工业自动化领域发挥着关键作用&#xf…

C# 使用FluentHttpClient请求WebApi

写在前面 FluentHttpClient 是一个REST API 异步调用 HTTP 客户端&#xff0c;调用过程非常便捷&#xff0c;采用流式编程&#xff0c;可以将所有请求所需的参数一次性发送&#xff0c;并直接获取序列化后的结果。 老规矩从NuGet上安装该类库&#xff1a; 这边一定要认准是 P…

科技云报道:至简至强,新一代服务器的算力美学

科技云报道原创。 在这个时代&#xff0c;数据和计算的边界正在迅速扩张。 随着云计算、物联网和人工智能的日益成熟&#xff0c;对算力的需求已经突破了传统的限制&#xff0c;进入了一个全新的阶段。在这个阶段&#xff0c;不仅是算力的量级发生了变化&#xff0c;其性质和…

计网02-计算机网络参考模型

一、OSI七层参考模型 1、分层的思想 分层模型用于网络协议的设计方法&#xff0c;本质是将网络节点间复杂的通信问题分成若干简单的问题逐一解决&#xff0c;通过网络的层次去找问题&#xff0c;将复杂问题简单化。 2、OSI参考模型 由于早期计算机厂商使用的是私有的网络模…

图书管理系统jsp + servlet+mysql

图书管理系统 项目使用jsp servletmysql实现&#xff1b; 登陆注册 首页 首页显示图书信息 图书管理 1添加书籍 2查询书籍 3预览书籍 4修改书籍 用户管理 1查询用户 2修改用户 3 删除用户 链接&#xff1a;https://pan.baidu.com/s/1QXK--ypb6OadbmKFlc0jUQ

c语言:[输出函数]与[输入函数]|要点简述

一、【输出函数】 printf() 与 puts()的不同点 1、printf()函数 printf()支持单个字符%c的输出&#xff0c;以及字符串%s的输出。 (1)如果是以%c的形式输出&#xff0c;是一个字符一个字符的输出。因此&#xff0c;要用一个循环语句&#xff0c;把字符逐个输出。 (2)而用%…