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的直接使用,提高了程序的可靠性和可维护性。


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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Halcon计算一个区域的最大内接圆 inner_circle

Halcon计算一个区域的最大内接圆 该算子用于计算一个区域的最大内接圆&#xff0c;其原型如下&#xff1a; inner_circle(Regions : :: Row, Column, Radius)参数1&#xff1a;Regions 表示输入的区域。 参数2和3&#xff1a;Row、Column为输出参数&#xff0c;表示最大内接圆…

面试经典题---6.Z字形变换

6.Z字形变换 我的解法&#xff1a; 首先定义了3个变量&#xff1a;index、add和step。 index&#xff1a;当前处理字符在原字符串中的下标&#xff1b;add&#xff1a;Z字形中相邻两个字符在原字符串中的下标之差&#xff08;非固定值&#xff0c;值随着行的改变会发生变化&am…

Linux 上 Nginx 配置访问 web 服务器及配置 https 访问配置过程记录

目录 一、前言说明二、配置思路三、开始修改配置四、结尾 一、前言说明 最近自己搭建了个 Blog 网站&#xff0c;想把网站部署到服务器上面&#xff0c;本文记录一下搭建过程中 Nginx 配置请求转发的过程。 二、配置思路 web项目已经在服务器上面运行起来了&#xff0c;运行的端…

EtherCAT主站SOEM -- 13 --Qt-Soem通过界面按键控制 EtherCAT IO模块的io输出

EtherCAT主站SOEM -- 13 --Qt-Soem通过界面按键控制 EtherCAT IO模块的io输出 一 mainwindow.c 文件函数:1.1 自定义PDO配置2.2 主站初始化2.3 去motrorcontrol界面二 motrorcontrol.c 文件三 allvalue.h 文件该文档修改记录:总结一 mainwindow.c 文件函数: mainwindow主界…

性能分析与调优: Linux 性能分析60秒

目录 一、实验 1.环境 2.Linux性能分析60秒 一、实验 1.环境 &#xff08;1&#xff09;主机 表1-1 主机 主机架构组件IP备注prometheus 监测 系统 prometheus、node_exporter 192.168.204.18grafana监测GUIgrafana192.168.204.19agent 监测 主机 node_exporter192.168…

数据分析基础之《numpy(6)—IO操作与数据处理》

了解即可&#xff0c;用panads 一、numpy读取 1、问题 大多数数据并不是我们自己构造的&#xff0c;而是存在文件当中&#xff0c;需要我们用工具获取 但是numpy其实并不适合用来读取和处理数据&#xff0c;因此我们这里了解相关API&#xff0c;以及numpy不方便的地方即可 2…

java解析json复杂数据的两种思路

文章目录 一、原始需求二、简单分析三、具体实现一1. api接口2. 接口返回3. json 数据解析1.&#xff09;引入Jackson库2.&#xff09;定义实体3.&#xff09;解析json字符串4.&#xff09;运行结果 4. 过程分析 四、具体实现二1. 核心代码2.运行结果 五、方案比较六、源码传送…

python数据可视化之折线图案例讲解

学习完python基础知识点&#xff0c;终于来到了新的模块——数据可视化。 我理解的数据可视化是对大量的数据进行分析以更直观的形式展现出来。 今天我们用python数据可视化来实现一个2023年三大购物平台销售额比重的折线图。 准备工作&#xff1a;我们需要下载用于生成图表的第…

MySQL之视图外连接、内连接和子查询的使用

一、视图 1.1 含义 虚拟表&#xff0c;和普通表一样使用 1.2 操作 创建视图 create view 视图名 as 修改视图 方式一&#xff1a; create or replace view 视图名 as 【查看视图相关字段】 方式二&#xff1a; alter view 视图名 as 【查看的SQL语句】 查看视图 方式一&…

【算法笔记】深入理解dfs(两道dp题)

DFS过程的概述 一个一个节点的搜&#xff0c;如果是树状结构的话&#xff0c;先找到最左边那一条分支搜到最后一个节点&#xff0c;这个时候最后一个节点&#xff08;假设是b&#xff09;的数据会被更新&#xff08;具体看题目的要求&#xff09;&#xff0c;然后返回到上一个…

服务器终端快速下载coco数据集

######解压到当前文件夹 sudo apt-get install aria2 aria2c -c <url> #<url>即为官网下载地址# url # download images http://images.cocodataset.org/zips/train2017.zip http://images.cocodataset.org/zips/val2017.zip# download annotations http://i…

Pytest的测试报告——Allure

一、html-report测试报告 html-report测试报告。是pytest下基本的测试报告。要使用pytest-html测试报告&#xff0c;就要确保python版本在3.6及以上即可。本身pytest所提供的测试结果汇总&#xff0c;是基于控制台的文本输出形式。 pytest-html是基于HTML格式实现的测试报告的…

Spark调优解析-spark数据倾斜优化2(七)

1 数据倾斜优化 1.1为何要处理数据倾斜&#xff08;Data Skew&#xff09; 什么是数据倾斜 对Spark/Hadoop这样的大数据系统来讲&#xff0c;数据量大并不可怕&#xff0c;可怕的是数据倾斜。 何谓数据倾斜&#xff1f;数据倾斜指的是&#xff0c;并行处理的数据集中&#xf…

py的基础语法

前言:本章节主播会详细描述py的基础语法&#xff0c;其中包括语句之间的转换和拼接&#xff0c;内容较多&#xff0c;友友们加油 目录 一.字面量 1.1关于字面量 1.2举例 1.3小结 二.注释 2.1关于注释 2.2举例 2.3小结 三.变量 3.1关于变量 3.2举例 3.3小结 四.数据…

Iceberg从入门到精通系列之十九:分区

Iceberg从入门到精通系列之十九&#xff1a;分区 一、认识分区二、Iceberg的分区三、Hive 中的分区四、Hive 分区问题五、Iceberg的隐藏分区六、分区变换七、分区变换 一、认识分区 分区是一种通过在写入时将相似的行分组在一起来加快查询速度的方法。 例如&#xff0c;从日志…

LeetCode 2807.在链表中插入最大公约数

【LetMeFly】2807.在链表中插入最大公约数 力扣题目链接&#xff1a;https://leetcode.cn/problems/insert-greatest-common-divisors-in-linked-list/ 给你一个链表的头 head &#xff0c;每个结点包含一个整数值。 在相邻结点之间&#xff0c;请你插入一个新的结点&#x…

【MYSQL】MYSQL 的学习教程(十一)之 MySQL 不同隔离级别,都使用了哪些锁

聊聊不同隔离级别下&#xff0c;都会使用哪些锁&#xff1f; 1. MySQL 锁机制 对于 MySQL 来说&#xff0c;如果只支持串行访问的话&#xff0c;那么其效率会非常低。因此&#xff0c;为了提高数据库的运行效率&#xff0c;MySQL 需要支持并发访问。而在并发访问的情况下&…

ASP.NET Core中实现个人资料上传图片功能

当用户需要在ASP.NET Core中实现修改个人资料的功能时&#xff0c;其中一个常见的需求就是允许上传个人头像图片。下面将详细介绍如何在ASP.NET Core中实现修改个人资料上传图片的功能。 步骤一&#xff1a;控制器中添加一个HttpPost方法 首先&#xff0c;我们在控制器中添加…

Linux时间同步和时间设置

时间分为&#xff1a; 1、hwclock&#xff1a;用于查看硬件时间 hwclock -r&#xff08;--show&#xff1a;读取硬件时钟并打印结果&#xff09; &#xff1a;查看硬件时间 hwclock -s &#xff1a;系统时间向硬件时间同步 hwclock -w &#xff1a;硬件时间向系统时间同步 …

Dash+Plotly | Web应用开发(1)

本文为https://github.com/CNFeffery/DataScienceStudyNotes的学习笔记&#xff0c;部分源码来源于此仓库。 本期内容主要为基础概念、web布局方法和交互回调。 文章目录 Dash的主要模块Highlightlayoutcallback 惰性交互阻止初次回调忽略回调匹配错误控制部分回调输出不更新获…