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.mzph.cn/news/602004.shtml

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

相关文章

【多模态】ALBEF

ALBEF 论文信息 标题:Align before Fuse: Vision and Language Representation Learning with Momentum Distillation 作者:Junnan Li(Salesforce Research) 期刊:NeurIPS 2021 发布时间与更新时间:2021.07.16 2021.10.07 主题:多模态、预训练、图像、文本、对比学习、知…

3D人体姿态估计(教程+代码)

3D人体姿态估计是指通过计算机视觉和深度学习技术&#xff0c;从图像或视频中推断出人体的三维姿态信息。它是计算机视觉领域的一个重要研究方向&#xff0c;具有广泛的应用潜力&#xff0c;如人机交互、运动分析、虚拟现实、增强现实等。 传统的2D人体姿态估计方法主要关注通…

欧科云链研究院:奔赴2024,Web3与AI共振引爆数字时代潘多拉魔盒

出品&#xff5c;欧科云链研究院 2024年&#xff0c;Web3与AI两个数字科技的巅峰碰撞&#xff0c;欧科云链研究院探索AI与Web3的技术融合&#xff0c;与澎湃科技联合发布2024年展望&#xff0c;原标题为《2024年展望&#xff1a;Web3与AI共振引爆可信数字社会》&#xff0c;共…

小程序如何配置扫码点餐功能

在餐饮行业中&#xff0c;通过小程序扫码点餐是一种非常方便和高效的方式。下面具体介绍怎么给小程序设置扫码点餐功能。 一、给每个桌子设置单独的小程序码。管理员点击个人中心->我的管理->更多->门店码。 生成小程序码页面&#xff0c;各个字段解释如下。 会员卡…

【Golang】Json 无法表示 float64 类型的 NaN 以及 Inf 导致的 panic

【Golang】Json 无法表示 float64 类型的 NaN 以及 Inf 导致的 panic 原因 golang 服务出现了 panic&#xff0c;根据 panic 打印出的堆栈找到了问题代码&#xff0c;看上去原因是&#xff1a;json 序列化时&#xff0c;遇到了无法序列化的内容 [panic]: json: unsupported …

机器人控制箱内部包含什么零件,有什么作用。

问题描述&#xff1a;机器人控制箱内部包含什么零件&#xff0c;有什么作用。 问题解答&#xff1a; 机器人控制箱是机器人系统中的一个关键组件&#xff0c;负责控制和协调机器人各个部件的运动和功能。控制箱的内部通常包含以下主要零件和模块&#xff1a; 主控制器&#x…

跟着小德学C++之日志记录

嗨&#xff0c;大家好&#xff0c;我是出生在达纳苏斯的一名德鲁伊&#xff0c;我是要立志成为海贼王&#xff0c;啊不&#xff0c;是立志成为科学家的德鲁伊。最近&#xff0c;我发现我们所处的世界是一个虚拟的世界&#xff0c;并由此开始&#xff0c;我展开了对我们这个世界…

数学之美一两处

引言 吴军博士的《数学之美》科普性地介绍了自然语言处理、搜索引擎、语音识别、智能导航等人工智能应用&#xff0c;一些看似很智能、高大上的应用&#xff0c;其背后的数学原理往往却并不复杂&#xff0c;体现了数学之美&#xff01; 如果数学能够这样教&#xff0c;可能很多…

在未来的一个时期,阿里将会和AI电商联系在一起

当张勇退场&#xff0c;以蔡崇信和吴泳铭为代表的「元老们」&#xff0c;开始执掌阿里。 对于现在的阿里来讲&#xff0c;或许&#xff0c;没有比找到能真正带来改变的全新发展方向&#xff0c;更加迫切的事情了。 正是因为如此&#xff0c;我们才看到了&#xff0c;当拼多多…

【Bootstrap5学习 day12】

Bootstrap5 导航 Bootstrap5提供了一种简单快捷的方法来创建基本导航&#xff0c;它提供了非常灵活和优雅的选项卡和Pills等组件。Bootstrap5的所有导航组件&#xff0c;包括选项卡和Pillss&#xff0c;都通过基本的.nav类共享相同的基本标记和样式。 创建基本导航 要创建简单…

PostgreSQL的学习心得和知识总结(一百二十七)|为 Postgres 编写存储引擎:一种内存表访问方法

目录结构 注:提前言明 本文借鉴了以下博主、书籍或网站的内容,其列表如下: 1、参考书籍:《PostgreSQL数据库内核分析》 2、参考书籍:《数据库事务处理的艺术:事务管理与并发控制》 3、PostgreSQL数据库仓库链接,点击前往 4、日本著名PostgreSQL数据库专家 铃木启修 网站…

Mybatis分页插件PageHelper的配置和使用

文章目录 每页10条记录&#xff0c;取第一页&#xff0c;返回的是前10条记录每页10条记录&#xff0c;取第二页&#xff0c;返回的是第11条记录&#xff0c;到第20条记录&#xff0c; MySQL对分页的支持 简单来说MySQL对分页的支持是通过limit子句。请看下面的例子。 limit关键…

钢铁企业电力设计手册(上下册)总目录

《钢铁企业电力设计手册》总目录 上册 第1章 高压供配电系统 第2章 负荷计算 第3章 供电系统中的有功和无功冲击负荷 第4章 短路电流计算 第5章 电压偏差和电压波动 第6章 电技术节能 第7章 自备电厂及柴油机组发电 第8章 电弧炉供电 第9章 能源管理系统&#xff08;电力部分&a…

使用pagehelper插件进行分页查询

一、导入mybatis和pagehelper坐标 <dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.0</version> </dependency> <dependency><groupId&…

springboot整合mongodb批量修改和添加索引,与设置mongodb保存更新超时时间

1&#xff1a;创建字段索引 collection 是集合名称&#xff0c;keys 是一个包含一个或多个字段名&#xff0c;options是排序方向&#xff0c;1正序&#xff0c;-1倒叙 db.collection.createIndex(keys, options)#单字段 db.collection.createIndex(name: 1)#多字段 db.collec…

Flink的检查点算法

Flink的恢复机制基于应用状态的一致检查点。在有状态的流应用中&#xff0c;一个一致性检查点是&#xff1a;在所有tasks处理了一个&#xff08;相同的&#xff09;输入后&#xff0c;当前时间点每个task的state副本。 在为application做一个一致性检查点时&#xff0c;一个基…

PDF.js实现搜索多个不同的关键词高亮显示效果

static\PDF\web\viewer.js 392行左右 // 自定义搜索关键词---------------------------------------- this.searchKeywords = keyword => {if (typeof PDFViewerApplication !== undefined) {PDFViewerApplication.eventBus.dispatch(find, {query: keyword,caseSensitive:…

代码随想录算法训练DAY22|二叉树8

算法训练DAY22|二叉树8 235. 二叉搜索树的最近公共祖先 力扣题目链接(opens new window) 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个结点 p、q&#xff0c;最近公共祖先表示为一个结点…

PEFT: 在低资源硬件上对十亿规模模型进行参数高效微调

1 引言 最近&#xff0c;深度学习的研究中出现了许多大型预训练模型&#xff0c;例如 GPT-3、BERT 等&#xff0c;这些模型可以在多种自然语言处理任务中取得优异的性能表现。而其中&#xff0c;ChatGPT 模型因为在对话生成方面的表现而备受瞩目&#xff0c;成为了自然语言处理…

sublime text 3 分屏和关闭分屏

有时候需要编辑多个地方的代码&#xff0c;开多个编辑器又太麻烦&#xff0c;那么Sublime自带的分屏快捷键可以解决烦恼。 Altshift2 分为2列 Altshift3 分为3列 Altshift4 分为4列 Altshift5 分为2行2列 Altshift8 分为2行 Altshift9 分为3行 取消分屏&#xff1a;Alts…