C++中的new和delete

相关文章

C++智能指针


文章目录

  • 相关文章
  • 前言
  • 一、new 运算符
    • 1. operator new 函数的范围
    • 2. 在类中重载new运算符
    • 3. 分配失败
  • 二、delete 运算符
    • 1. 内存泄露统计示例
    • 2. 在类中重载delete运算符
  • 总结


前言

  在C++中,new和delete是用于动态内存管理的运算符,它们允许程序在运行时动态地分配和释放内存,而不需要在编译时知道确切的内存需求。动态内存分配是指在程序运行时根据需要分配内存空间,而静态内存分配是指在编译时分配内存空间。new和delete是C++中实现动态内存分配和释放的关键工具。

  new运算符用于在堆上动态分配内存。它可以用于分配单个对象或数组。当使用new来分配单个对象时,它会返回一个指向所分配内存空间的指针,并自动调用对象的构造函数来初始化对象。当使用new来分配数组时,它会分配足够的内存来存储整个数组,并返回指向数组第一个元素的指针。这样,程序可以根据需要动态地创建数组,而不需要在编译时知道数组的大小。

  delete运算符用于释放由new分配的内存。对于单个对象,使用delete;对于数组,使用delete[]。当不再需要动态分配的内存时,应该使用delete来释放内存,以防止内存泄漏。delete会调用对象的析构函数来清理对象,并释放所分配的内存。这样,程序可以在不需要内存时及时释放它,以避免内存资源的浪费。

  new和delete提供了灵活的内存管理机制,使程序能够根据需要动态地分配和释放内存。然而,它们需要谨慎使用,因为错误的使用可能导致内存泄漏、悬空指针等问题。例如,在使用new分配内存后,如果忘记使用delete释放内存,就会导致内存泄漏;而在使用delete释放内存后,如果继续使用指向已释放内存的指针,就会导致悬空指针问题。因此,在使用new和delete时,需要确保正确地匹配内存的分配和释放,并避免出现悬空指针的情况。


  C++ 支持使用 new 和 delete 运算符动态分配和解除分配对象。 这些运算符为来自称为“自由存储”(也称为“堆”)的池中的对象分配内存。 new 运算符调用特殊函数 operator new,delete 运算符调用特殊函数 operator delete。

一、new 运算符

operator new的第一个参数必须为 size_t 类型,且返回类型始终为 void*,编译器将如下语句转换为对函数 operator new 的调用:

char *p = new char[64];

重复调用 operator new 会返回不同的地址(指针)。

如果要申请的的存储空间为零字节,operator new 将返回指向不同对象的指针:

#include <iostream>
using namespace std;int main()
{char *p1 = new char[0];char *p2 = new char[0];char *p3 = new char[0];cout << "p1=0x" << (int*)p1 << endl;cout << "p2=0x" << (int*)p2 << endl;cout << "p3=0x" << (int*)p3 << endl;return 0;
}

在这里插入图片描述

如果分配请求的内存不足,operator new 会引发 std::bad_alloc 异常。 或者,如果使用了 placement 形式 new(std::nothrow),或者链接在非引发的 operator new 支持中,它将返回 nullptr

1. operator new 函数的范围

运算符范围
::operator new全局
class-name::operator new

在使用 new 运算符分配内置类型的对象、不包含用户定义的 operator new 函数的类类型的对象和任何类型的数组时,将调用全局 operator new 函数。 在使用 new 运算符分配类类型的对象时(其中定义了 operator new),将调用该类的 operator new

2. 在类中重载new运算符

示例:

#include <memory.h>
#include <iostream>
using namespace std;class Test
{
public:Test() {cout << "Test()" << endl;}void *operator new(size_t size){//可以自定义空间申请规则cout << "operator new" << endl;return malloc(size);}
};int main()
{Test *p = new Test;return 0;
}

执行结果:
在这里插入图片描述

执行流程:
在这里插入图片描述

在类声明中支持数组的 new 运算符。 例如:

#include <memory.h>
#include <iostream>
using namespace std;class Test
{
public:Test() {cout << "Test()" << endl;}void *operator new[](size_t size){cout << "operator new[]" << endl;return malloc(size);}
};int main()
{Test *p = new Test[5];return 0;
}

执行结果:
在这里插入图片描述

3. 分配失败

C++ 标准库中的 new 函数支持自 C++98 以来在 C++ 标准中指定的行为。 如果分配请求的内存不足,operator new 会引发 std::bad_alloc 异常。标准 C++ 要求分配器引发 std::bad_alloc 或派生自 std::bad_alloc 的类。 可以处理此类异常,如以下示例所示:

#include <iostream>
using namespace std;int main()
{size_t n = 20000000000L;try {int *p = new int[n];cout << p << endl;}catch (bad_alloc& ex) {cout << "申请内存失败: " << ex.what() << endl;}return 0;
}

执行结果:

在这里插入图片描述

二、delete 运算符

  可使用 delete 运算符释放使用 new 运算符动态分配的内存。 delete 运算符调用 operator delete 函数,该函数将内存释放回可用池。 使用 delete 运算符也会导致调用类析构函数(如果存在)。

1. 内存泄露统计示例

  能过自定义 operator newoperator delete 函数,来记录申请内存和释放的次数,判断是否存在内存泄露,示例如下:

#include <iostream>
using namespace std;bool bLog = 0;
int  nAllocated = 0;void *operator new(size_t size) { ++nAllocated;cout << "申请内存 " << nAllocated<< " 大小 " << size<< "\n";return malloc(size);
}void operator delete(void *p) {--nAllocated;clog << "释放内存 " << nAllocated<< "\n";free(p);
}int main() {for (int i = 0; i < 10; ++i) {char *p = new char[10];delete[] p;}cout << nAllocated << endl;return 0;
}

2. 在类中重载delete运算符

示例如下:

#include <iostream>
using namespace std;class Test {
public:Test() {cout << "Test()" << endl;}~Test() {cout << "~Test()" << endl;}void *operator new(size_t size){cout << "operator new" << endl;return malloc(size);}void *operator new[](size_t size){cout << "operator new[]" << endl;return malloc(size);}void operator delete (void* p) {cout << "operator delete(void*)" << endl;free(p);}void operator delete[](void* p) {cout << "operator delete[](void*)" << endl;free(p);}};int main() {Test *p1 = new Test;delete p1;cout << "------------------\n";Test *p2 = new Test[5];delete[] p2;return 0;
}

执行结果:
在这里插入图片描述
执行过程:
在这里插入图片描述


总结

  new和delete是C++中用于动态内存管理的运算符,它们提供了灵活的内存分配和释放机制,但需要谨慎使用以避免内存泄漏和悬空指针等问题。随着智能指针的引入,程序员可以更安全地进行动态内存管理,减少了对new和delete的直接使用,提高了程序的可靠性和可维护性。


✍结尾 ❤️ 感谢您的支持和鼓励关注不迷路✍

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

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

相关文章

el-upload上传文件

需求&#xff1a;选中或拖拽文件后&#xff0c;使用http-request属性实现自动上传&#xff0c;并根据后端传回来的结果显示错误和控制fileList的显示&#xff0c;如果后端返回成功&#xff0c;则文件显示在文件列表处&#xff0c;如果后端返回失败&#xff0c;则文件列表不显示…

听GPT 讲Rust源代码--compiler(15)

File: rust/compiler/rustc_arena/src/lib.rs 在Rust源代码中&#xff0c;rustc_arena/src/lib.rs文件定义了TypedArena&#xff0c;ArenaChunk&#xff0c;DroplessArena和Arena结构体&#xff0c;以及一些与内存分配和容器操作相关的函数。 cold_path<F: FnOnce,drop,new,…

基于商品列表的拖拽排序后端实现

目录 一&#xff1a;实现思路 二&#xff1a;实现步骤 二&#xff1a;实现代码 三&#xff1a;注意点 一&#xff1a;实现思路 后台实现拖拽排序通常需要与前端进行配合&#xff0c;对商品的列表拖拽排序&#xff0c;前端需要告诉后端拖拽的元素和拖动的位置。 这里我们假…

杰发科技AC7840——Eclipse环境DMA注意事项

0.序 用 户 使 用 DMA 时 &#xff0c; 所 有 DMA 搬 运 的 SRAM 数 据 都 必 须 存 放 在 SRAM_U 区 (0x20000000~0x2000EFFF) 。 1. 修改办法 第一步&#xff1a; RAM定义 /* Specify the memory areas */ MEMORY {FLASH (rx) : ORIGIN 0x00000000, LENGT…

听GPT 讲Rust源代码--compiler(25)

File: rust/compiler/rustc_target/src/spec/mod.rs 在Rust的源代码中&#xff0c;rust/compiler/rustc_target/src/spec/mod.rs文件的作用是定义和实现有关目标平台的规范。 SanitizerSet是一个结构体&#xff0c;用于表示目标平台上存在的sanitizer集合。 TargetWarnings是一…

AI与5G、IDC等成为数字经济的重要基础设施

AI与5G、IDC等已经成为数字经济的重要基础设施&#xff0c;它们的影响和作用不容忽视。随着技术的迅速发展&#xff0c;AI在各行各业都得到了广泛应用&#xff0c;并成为数字经济的核心驱动力之一。 首先&#xff0c;AI的兴起为数字经济带来了巨大的机遇。AI技术可以帮助企业从…

YOLOv5改进 | 检测头篇 | 增加辅助检测头利用AFPN改进Head(附详细修改教程)

一、本文介绍 本文给大家带来的改进机制是利用今年新推出的AFPN(渐近特征金字塔网络)来优化检测头,AFPN的核心思想是通过引入一种渐近的特征融合策略,将底层、高层和顶层的特征逐渐整合到目标检测过程中。这种渐近融合方式有助于减小不同层次特征之间的语义差距,提高特征…

如何使用可视化管理工具DockerUI远程管理docker容器

文章目录 前言1. 安装部署DockerUI2. 安装cpolar内网穿透3. 配置DockerUI公网访问地址4. 公网远程访问DockerUI5. 固定DockerUI公网地址 前言 DockerUI是一个docker容器镜像的可视化图形化管理工具。DockerUI可以用来轻松构建、管理和维护docker环境。它是完全开源且免费的。基…

学习笔记——C++运算符之逻辑运算符

作用&#xff1a;用于根据表达式的真值返回真值或假值 逻辑运算符有以下符号&#xff1a; #include<bits/stdc.h> using namespace std; int main(){// 逻辑运算符 非 !int a10;//在c中&#xff0c;除了0均是真 cout<<!a<<endl;//0 cout<<!!a<<…

Pycharm打包程序为exe文件

Pycharm打包程序为exe文件 【一】导入模块pyinstaller 【1】图片说明 【2】文字说明 根据图片顺序执行 首先点击file进入settings界面&#xff0c;在setting界面找到Project下面的Python Interpretor&#xff0c;点击号进行模块的添加在搜索框中输入pyinstaller&#xff0c;…

UE5 给自己的数字人重定向Mixamo动画

1 、准备动画骨格文件&#xff0c;动画文件&#xff0c;下面是Mixamo动画素材下载网站Mixamo动画骨格文件下载网站https://www.mixamo.com/2、下载动画骨格文件&#xff0c;打Mixamo网站&#xff0c;选择Characters骨格菜单&#xff0c;在下面找到对应的骨格。如下图所示&#…

静态网页设计——环保网(HTML+CSS+JavaScript)(dw、sublime Text、webstorm、HBuilder X)

前言 声明&#xff1a;该文章只是做技术分享&#xff0c;若侵权请联系我删除。&#xff01;&#xff01; 感谢大佬的视频&#xff1a; https://www.bilibili.com/video/BV1BC4y1v7ZY/?vd_source5f425e0074a7f92921f53ab87712357b 使用技术&#xff1a;HTMLCSSJS&#xff08;…

数据库攻防学习之MySQL

MySQL 0x01mysql学习 MySQL 是瑞典的MySQL AB公司开发的一个可用于各种流行操作系统平台的关系数据库系统&#xff0c;它具有客户机/服务器体系结构的分布式数据库管理系统。可以免费使用使用&#xff0c;用的人数很多。 0x02环境搭建 这里演示用&#xff0c;phpstudy搭建的…

【源码解析】Apache RocketMQ发送消息源码

send message源码解析 引入 send message方法作为我们经常使用的方法&#xff0c;平时我们很难去关注他底层到底做了什么。大部分人只知道通过send message方法可以将消息发送到broker&#xff0c;然后供消费者进行消费。其实不然&#xff0c;消息从客户端发送到broker&#x…

Nginx快速入门:Nginx实现高可用|结合keepalived实现主备节点(九)

0. 引言 在生产中我们要尽可能避免单点故障&#xff0c;nginx也不例外&#xff0c;因此搭建主备节点必不可少&#xff0c;今天我们来学习下如何利用keepalived实现主备 1. keepalived简介 keepalived 是一个LINUX系统中开源的负载均衡和故障转移软件&#xff0c;它主要用于高…

Vue新手村(一)

目录 1、Vue简介——Vue的特点 2、Vue的第一个页面 3.Vue的简单使用介绍 3.1、{{ }}的使用 3.2、v-text和v-html 3.2.1、v-text和{{ }}的区别 3.2.2、v-html和v-text的区别 3.3、v-on【事件绑定】 3.3.1、绑定事件的语法 3.3.2、语法简化 3.3.3、传参 3.4、v-show和…

Elasticsearch基本操作之索引操作

本文说下Elasticsearch基本操作之索引操作 文章目录 概述创建索引创建索引示例重复创建索引示例 查看索引查看所有索引查看单个索引 删除索引删除索引 概述 由于是使用命令来操作Elasticsearch&#xff0c;可以使用kibana&#xff0c;postman和apifox等工具 我使用了apifox来执…

Access数据库C#读写验证

1、数据库简介 Access数据库是一个相当古老的文件型数据库&#xff0c;主打一个简单方便&#xff0c;没有复杂的安装过程&#xff0c;没有庞大的后端管理&#xff0c;整个数据库就是一个文件。可以像普通文件一样复制和修改&#xff0c;可以同时读写。 在小型系统中&#xff0c…

Java序列化篇----第一篇

系列文章目录 文章目录 系列文章目录前言一、什么是java序列化,如何实现java序列化?二、保存(持久化)对象及其状态到内存或者磁盘三、序列化对象以字节数组保持-静态成员不保存四、序列化用户远程对象传输前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,…

探索生成式AI:自动化、问题解决与创新力

目录 自动化和效率&#xff1a;生成式AI的颠覆力量 解谜大师生成式AI&#xff1a;如何理解和解决问题 创新与创造力的启迪&#xff1a;生成式AI的无限潜能 自动化和效率&#xff1a;生成式AI的颠覆力量 1. 神奇的代码生成器&#xff1a;生成式AI可以帮助开发人员像魔术一样快…