C++动态内存管理:new 和 delete

news2024/11/26 17:21:33

目录

一.前言

二.new和delete的基本使用

1.new/delete操作内置类型

三.定位new表达式(placement-new)

四.new操作数出现内存申请错误时的处理方式:抛异常

五.new和malloc的区别


一.前言

C++沿用了C语言的底层内存管理机制:

然而在动态内存管理方面,C语言的动态内存管理机制(malloc/calloc/realloc/free)在两个主要方面无法适用于C++中引入的复杂类对象

  1. C语言的动态内存函数为类对象开辟堆区空间时,无法调用类的构造函数,free()函数释放类对象所占空间时无法调用类的析构函数
  2. C语言的动态内存函数的报错机制不适用于C++的面向对象的编程模式。

二.new和delete的基本使用

1.new/delete操作内置类型

new和delete是C++中用于在程序中动态申请和释放堆区空间操作符。

基本使用方法:

void Test()
{
    动态申请一个int类型的空间
    int* ptr4 = new int;
     

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


    动态申请3个int类型的空间
    int* ptr6 = new int[3];
    
    
    释放掉ptr4指向的堆区动态开辟的内存块
    delete ptr4;
    ptr4 = nullptr;
    


    释放掉ptr5指向的堆区动态开辟的内存块
    delete ptr5;
    ptr5= nullptr;

    
    释放掉ptr6指向的堆区动态开辟的内存块(对于连续开辟的空间要加[])
    delete[] ptr6;
    ptr6 = nullptr;
}

  •  申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用
     new[]和delete[],注意:匹配起来使用
  • new会根据申请创建的元素类型自动返回相应类型的指针,其返回值无须进行强制类型转换
  • new申请的数组可以以如下的方式进行初始化:

 

2.new和delete操作自定义类型

new为一个类对象申请堆区内存空间后,会自动调用其构造函数

class Date
{
public:
	Date(int year=0,int day =0)           Date类的构造函数
		:_day(day)
		,_year(year)
	{
		cout << "constructor" << endl;
	}
private:
	int _day;
	int _year;
};



int main()
{
	Date* ptr = new Date(2022,360);         new一个Date对象
	return 0;
}

delete释放掉一个动态申请的类对象的内存空间前,会自动调用其析构函数。

class Date
{
public:
	Date(int year=0,int day =0)             //Date的构造函数
		:_day(day)
		,_year(year)
	{
		cout << "constructor" << endl;
	}
	~Date()									//Date的析构函数
	{
		cout << "destroy" << endl;
	}
private:
	int _day;
	int _year;
};



int main()
{
	Date* ptr = new Date(2022,360);		//new一个Date对象

	delete ptr;							//释放对象

	return 0;
}

C++设计new和delete这两个操作符的其中一个目的之一就是为了在动态申请和释放对象时能够调用其构造函数和析构函数,这一点对于一些申请了额外内存资源的复杂对象(比如栈对象)是非常重要的。

三.定位new表达式(placement-new)

定位new表达式​​​​​用于调用动态开辟好的类对象的构造函数初始化一个对象(即显式调构造函数)

使用格式:
(1)new (place_address) type

(2)new (place_address) type(initializer-list)
place_address必须是一个指针(指向动态开辟的空间),initializer-list是类型的初始化列表

比如:

class Date
{
public:
	Date(int year=0,int day =0)             Date的构造函数
		:_day(day)
		,_year(year)
	{
		cout << "constructor" << endl;
	}
	~Date()									Date的析构函数
	{
		cout << "destroy" << endl;
	}
private:
	int _day;
	int _year;
};
int main()
{
	Date* ptr = (Date*)malloc(sizeof(Date));  malloc函数不会主动调用对象的构造函数
	new (ptr)Date;						      定位new表达式


	ptr->~Date();							  显式调用析构函数
	free(ptr);							      释放对象

	return 0;
}

定位new表达式在实际中一般是配合内存池使用。因为内存池分配出的内存没有初始化,需要使用new的定义表达式进行显示调用类对象构造函数进行初始化

四.new操作数出现内存申请错误时的处理方式:抛异常

  • 面向过程的语言(C语言),处理动态内存申请错误的方式返回空指针并给出错误码
  • 面向对象的语言,处理动态内存申请错误的方式一般是抛异常(通过对象来实现)--try catch
void test()
{
	char* ptr = new char[0x7fffffff];  //申请2个G的堆区空间(过大会导致申请失败)
}

int main()
{
	try                                 try用于确定需要检测的代码语句
	{
		test();
	}
	catch (const std::exception&)       catch用于捕获异常
	{    
		cout << "new failed" << endl;
	}
	return 0;
}

  • try用于确定需要检测的代码语句catch用于捕获异常

上述抛异常的报错机制更符合处理复杂对象的动态内存管理错误问题

五.new和malloc的区别

  1. malloc和free是函数,new和delete是操作符(关键字)。
  2. malloc申请的空间不会初始化,new可以初始化。
  3. malloc申请空间时,需要手动计算空间大小并传递,new只需在其后写上空间的类型即可,如果是多个对象,[ ]中指定对象个数即可。
  4. malloc的返回值为void*, 在使用时必须强转,new不需要。
  5. malloc申请空间失败时,返回的是NULL,因此使用时必须进行指针判空,new不需要,但是new需要捕获异常。
  6. 申请类对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new在申请空间后会调用构造函数完成对象的初始化delete在释放空间前会调用析构函数完成空间中资源的清理

 

 

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

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

相关文章

Java——三角形最小路径和

题目链接 leetcode在线oj题——三角形最小路径和 题目描述 给定一个三角形 triangle &#xff0c;找出自顶向下的最小路径和。 每一步只能移动到下一行中相邻的结点上。相邻的结点 在这里指的是 下标 与 上一层结点下标 相同或者等于 上一层结点下标 1 的两个结点。也就是…

AcWing 1057. 股票买卖 IV(状态机DP)

AcWing 1057. 股票买卖 IV &#xff08;1&#xff09;问题 &#xff08;2&#xff09;分析 这道题我们首先得明确一点&#xff0c;我们只有一支股票&#xff0c;只是这支股票在不同天有着不同的价格&#xff0c;因此我们可以把天作为单位划分不同的状态。同时这道题中还有一个…

极限存在准则 两个重要极限——“高等数学”

各位uu们你们好呀&#xff0c;今天小雅兰要学习的内容仍然是高等数学&#xff0c;是为&#xff1a;极限存在准则 两个重要极限。那现在就让我们一起进入高等数学的世界吧 引例 夹逼准则 准则Ⅰ 数列的夹逼准则 准则Ⅰ’ 函数的夹逼准则 重要极限Ⅰ 准则Ⅱ 单调有界数列必有极…

Servlet进阶1:Servlet原理

Servlet进阶一、Dispatcher二、doGet、doPost、Service方法的区别1. 三者联系2. 使用规则三、Servlet的生命周期四、Servlet、Servlet容器、Web服务器一、Dispatcher 一个Web App就是由一个或多个Servlet组成的&#xff0c;每个Servlet通过注解说明自己能处理的路径。早期的Se…

FreeRTOS-信号量详解

✅作者简介&#xff1a;嵌入式入坑者&#xff0c;与大家一起加油&#xff0c;希望文章能够帮助各位&#xff01;&#xff01;&#xff01;&#xff01; &#x1f4c3;个人主页&#xff1a;rivencode的个人主页 &#x1f525;系列专栏&#xff1a;玩转FreeRTOS &#x1f4ac;保持…

【algorithm】认真讲解前缀和与差分 (图文搭配)

&#x1f680;write in front&#x1f680; &#x1f4dd;个人主页&#xff1a;认真写博客的夏目浅石. &#x1f4e3;系列专栏&#xff1a;AcWing算法笔记 今天的月色好美 文章目录前言一、前缀和算法1.1 什么是前缀和&#xff1f;1.2 一维前缀和二、二维前缀和三、一维差分四…

Java---微服务---分布式搜索引擎elasticsearch(1)

分布式搜索引擎elasticsearch&#xff08;1&#xff09;1.elasticsearch1.1.了解ES1.1.1.elasticsearch的作用1.1.2.ELK技术栈1.1.3.elasticsearch和lucene1.1.4.为什么不是其他搜索技术&#xff1f;1.1.5.总结1.2.倒排索引1.2.1.正向索引1.2.2.倒排索引1.2.3.正向和倒排1.3.es…

表单标签的使用

1、input标签 场景&#xff1a;在网页中显示收集用户消息的表单效果&#xff0c;如登录页、注册页 通过type属性值的不同&#xff0c;展示不同的效果 type属性值说明text文本框&#xff0c;用于输入单行文本password密码框&#xff0c;用于输入密码radio单选框&#xff0c;用…

检查 malloc 函数返回内容的四个理由

写在前面&#xff1a; 一些开发人员可能对检查不屑一顾&#xff1a;他们故意不检查malloc函数是否分配了内存。他们的推理很简单——他们认为会有足够的记忆。如果没有足够的内存来完成操作&#xff0c;请让程序崩溃。似乎是一个糟糕的事实。 注意。在本文中&#xff0c;mall…

Opencv 之 DNN 与 CUDA综述

Opencv 之 DNN 与 CUDA 目录 Opencv官方手稿&#xff08;包含各模块API介绍及使用例程&#xff09; Opencv在github的仓库地址&#xff1a;https://github.com/opencvOpencv额外的测试数据 下载&#xff1a;https://github.com/opencv/opencv_extra #可通过git下载拉取 git c…

【算法练习】删除链表的节点

题源&#xff1a;牛客描述给定单向链表的头指针和一个要删除的节点的值&#xff0c;定义一个函数删除该节点。返回删除后的链表的头节点。1.此题对比原题有改动2.题目保证链表中节点的值互不相同3.该题只会输出返回的链表和结果做对比&#xff0c;所以若使用 C 或 C 语言&#…

pix2pix(二)训练图像尺寸及分配显卡

背景&#xff1a;新的数据集上&#xff0c;图像的大小为496496&#xff0c;与原尺寸512512不一样&#xff0c;不知道能否直接运行。另外&#xff0c;我们现在有了四张空余显卡服务器&#xff0c;并且新数据集的数据量较大&#xff0c;我们有空余的显卡资源加快训练。 目的&…

C++ 模板

在学习stl之前&#xff0c;我们就已经略微讲解了一些模板的知识&#xff0c;而现在&#xff0c;我们来进一步了解一下模板的相关知识 初步了解 目录 一. 非类型模板参数 二. 模板的特化 全特化 偏特化 三. 模板分离编译 四. 总结 一. 非类型模板参数 模板参数…

C进阶_结构体内存对齐

请看下面的代码&#xff0c;输出结果是多少&#xff1f; #include <stdio.h> int main() {struct S1{char c1;int i;char c2;};printf("%d\n", sizeof(struct S1));struct S2{char c1;char c2;int i;};printf("%d\n", sizeof(struct S2));return 0;…

Xmake v2.7.6 发布,新增 Verilog 和 C++ Modules 分发支持

Xmake 是一个基于 Lua 的轻量级跨平台构建工具。 它非常的轻量&#xff0c;没有任何依赖&#xff0c;因为它内置了 Lua 运行时。 它使用 xmake.lua 维护项目构建&#xff0c;相比 makefile/CMakeLists.txt&#xff0c;配置语法更加简洁直观&#xff0c;对新手非常友好&#x…

前端CSS学习之路-css002

&#x1f60a;博主页面&#xff1a;鱿年年 &#x1f449;博主推荐专栏&#xff1a;《WEB前端》&#x1f448; ​&#x1f493;博主格言&#xff1a;追风赶月莫停留&#xff0c;平芜尽处是春山❤️ 目录 CSS字体属性 一、字体系列 二、字体大小 三、字体粗细 四、文字样…

Docker安装nacos

首先将自己的服务器在配置上弄成docker的 然后再下方命令框中直接粘贴如下命令&#xff1a; docker run –name nacos -d -p 8848:8848 -p 9848:9848 -p 9849:9849 –restartalways -e JVM_XMS256m -e JVM_XMX256m -e MODEstandalone -v /usr/local/nacos/logs:/home…

基于多协议传感器的桥梁监测数据采集与管理系统设计

文章目录前言1、要求&#xff1a;2、系统框图2.1系统总体框图2.2、stm32通过AHT20采集温湿度框图&#xff1a;2.3、stm32通过modbus协议与上位机通信框图&#xff1a;3、ModBus协议1、协议概述2、Modbus主/从协议原理3、通用Modbus帧结构---协议数据单元(PDU)4、两种Modbus串行…

readonly与disabled对比

<!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <title>readonly与disabled</title> </head> <body> <!--readonly与disabled 都是只读不能修改…

传统推荐模型(二)协同过滤的进化——矩阵分解算法

传统推荐模型&#xff08;二&#xff09;协同过滤的进化——矩阵分解算法 针对协同过滤算法的头部效应较明显、泛化能力较弱的问题&#xff0c;矩阵分解算法被提出。矩阵分解在协同过滤算法中“共现矩阵”的基础上&#xff0c;加人了隐向量的概念&#xff0c;加强了模型处理稀…