C++中的new和delete

news2024/10/2 1:29:22

相关文章

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.coloradmin.cn/o/1362538.html

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

相关文章

优势演员-评论家算法 A2C

优势演员-评论家算法 A2C 优势演员-评论家算法 A2C主要思想目标函数 优势演员-评论家算法 A2C 前置知识&#xff1a;演员-评论家算法&#xff1a;多智能体强化学习核心框架 主要思想 AC 网络结构&#xff1a; 策略网络 - 演员: 这个网络负责根据当前的状态选择动作。它输出的是…

更改ERPNEXT源

更改ERPNEXT源 一&#xff0c; 更改源 针对已经安装了erpnext的&#xff0c;需要更改源的情况&#xff1a; 1, 更改为官方默认源, 进入frapp-bench的目录&#xff0c; 然后执行: bench remote-reset-url frappe //重设frappe的源为官方github地址。 bench remote-reset-url…

如何使用免费的ZeroSSL证书保护您的网站

使用 ZeroSSL 在您的站点上轻松实施 SSL。我们的指南涵盖了免费证书设置&#xff0c;确保安全和加密的用户连接。 如今&#xff0c;保护您的网站不仅是一种建议&#xff0c;而且是一种必需品。这就是SSL证书发挥作用的地方。它们对用户浏览器和网站之间传输的数据进行加密&…

复旦MBA科创青干营(二期):探索合肥科创企业的创新之路

11月18日-19日&#xff0c;复旦MBA科创青干营二期学生开启了整合实践活动的第三次企业参访&#xff0c;前往位于合肥的蔚来第二先进制造基地、安徽万邦医药科技股份有限公司和合肥国轩高科动力能源有限公司&#xff0c;在学术导师和科创企业家“双导师”的指导下&#xff0c;深…

LeetCode 每日一题 Day 3334(hard)35 ||二进制枚举/单调栈/链表遍历

2397. 被列覆盖的最多行数 给你一个下标从 0 开始、大小为 m x n 的二进制矩阵 matrix &#xff1b;另给你一个整数 numSelect&#xff0c;表示你必须从 matrix 中选择的 不同 列的数量。 如果一行中所有的 1 都被你选中的列所覆盖&#xff0c;则认为这一行被 覆盖 了。 形式…

MyBatis - 批量更新(update foreach)报错

在使用mybatis执行批量更新(update foreach)数据的时候报错如下&#xff1a; org.springframework.jdbc.BadSqlGrammarException: ### Error updating database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; c…

Merge还是Rebase?这次终于懂了

《Git分支管理&#xff1a;Merge还是Rebase&#xff1f;》 导语&#xff1a; 在Git的分支管理中&#xff0c;Merge和Rebase是两种常见的合并策略&#xff0c;每一种都有其优劣之处。究竟应该选择Merge还是Rebase&#xff0c;取决于项目的需求和团队的工作流程。本文将深入探讨…

金和OA C6 MailTemplates.aspx SQL注入漏洞复现

0x01 产品简介 金和OA协同办公管理系统软件(简称金和OA),本着简单、适用、高效的原则,贴合企事业单位的实际需求,实行通用化、标准化、智能化、人性化的产品设计,充分体现企事业单位规范管理、提高办公效率的核心思想,为用户提供一整套标准的办公自动化解决方案,以帮助…

手势识别+人脸识别+姿态估计(关键点检测+教程+代码)

手势识别和手势关键点检测是计算机视觉领域中的一个重要研究方向,涉及到从图像或视频中检测人手的位置和姿态信息,并推断出手势的意义。以下是一些可能用到的方法和技术: 手势识别 基于深度学习的手势识别 基于深度学习的手势识别是目前最流行的方法之一。它通常使用卷积神…

前置判断-Detection

检测模型回答存在幻觉可以通过检索外部知识进行校验&#xff0c;不过考虑生成式模型覆盖问题的广泛性&#xff0c;Self-Contradictory论文中评估chatgpt生成的回答中38.5%的内容无法通过Wiki等外部知识进行校验。 因此这里我们先介绍一种完全基于模型自身&#xff0c;不依赖外…

web学习笔记(十一)

目录 1.数据类型 1.1数据类型分类 &#xff08;1&#xff09;简单&#xff08;基本&#xff09;数据类型 &#xff08;2&#xff09;复杂&#xff08;特殊&#xff09;数据类型 1.2判断数据类型的方法 &#xff08;1&#xff09;常规判断方法&#xff1a; &#xff08;2…

jetson AGC orin 配置pytorch和cuda使用、yolov8 TensorRt测试

文章目录 1、安装环境1.1、检查系统环境1.2、下载安装pytorch1.3、下载安装torchvision1.3、测试安装是否成功 2、yolov8测试2.1、官方python脚本测试2.2、tensorrt 模型转换2.3、tensorrt c 测试 1、安装环境 1.1、检查系统环境 检查系统环境、安装jetpack版本&#xff0c;执…

UG装配-子装配

当我们在装配的时候&#xff0c;如果组件非常多&#xff0c;通常我们需要对其他部分零件进行单独的装配&#xff0c;然后在总成中使用&#xff0c;而不是在一个装配文件中对产品约束 我们在子装配中对各部件进行约束&#xff0c;默认状态下是无法在父装配中引用的 我们也可以在…

基于JavaWeb+SSM+Vue四六级词汇微信小程序系统的设计和实现

基于JavaWebSSMVue四六级词汇微信小程序系统的设计和实现 源码获取入口KaiTi 报告Lun文目录前言主要技术系统设计功能截图订阅经典源码专栏Java项目精品实战案例《500套》 源码获取 源码获取入口 KaiTi 报告 &#xff08;1&#xff09;课题背景 伴随着社会的快速发展, 现代社…

vim学习记录

目录 历史记录前言相关资料配置windows互换ESC和Caps Lock按键 基本操作替换字符串 历史记录 2024年1月2日, 搭建好框架,开始学习; 前言 vim使用很久了,但是都是一些基本用法,主要是用于配置Linux,进行一些简单的编写文档和程序.没有进行过大型程序开发,没有达到熟练使用的程…

解读 | Mint Blockchain 为何选择 OP Stack 作为 L2 技术方案?

Mint 是一个聚焦在 NFT 领域的创新型 L2 网络。Mint Blockchain 致力于促进 NFT 资产协议标准的创新和现实商业场景中 NFT 资产的大规模采用。今天这篇文章主要介绍一下 Mint Blockchain 开发者团队为什么选择了 OP Stack 技术方案&#xff0c;而不是其他家的 L2 方案。 我们将…

对Git的理解

1.Git介绍 Git 是一个免费的、开源的分布式版本控制系统&#xff0c;可以快速高效地处理从小型到大型的各种 项目。 2.版本控制 简单来说&#xff0c;就是记录文件的内容变化&#xff0c;记录下你每一次对文件的修改的版本&#xff0c;以免你改来改去想要回退到之前的版本的时…

centos用yum安装mysql详细教程

1 查询安装mysql的yum源,命令如下 ls /etc/yum.repos.d/ -l 界面如下图所示&#xff0c;未显示mysql的安装源 2 安装mysql相关的yum源,例如&#xff1a; 例如&#xff1a;rpm -ivh mysql57-community-release-el7.rpm 要注意 mysql的版本和系统的版本匹配 mysql57-communi…

SwiftUI之深入解析如何使用accessibilityChartDescriptor视图修饰符为视图构建音频图表

一、DataPoint 结构体 在 SwiftUI 中构建一个简单的条形图视图开始&#xff0c;该视图使用垂直条形显示一组数据点。如下所示&#xff0c;有一个 DataPoint 结构&#xff0c;用于描述条形图视图中的条形&#xff0c;它具有 id、标签、数值和填充颜色&#xff1a; struct Data…

面试官:String为什么要设计为不可变类

程序员的公众号&#xff1a;源1024&#xff0c;获取更多资料&#xff0c;无加密无套路&#xff01; 最近整理了一份大厂面试资料《史上最全大厂面试题》&#xff0c;Springboot、微服务、算法、数据结构、Zookeeper、Mybatis、Dubbo、linux、Kafka、Elasticsearch、数据库等等 …