C/C++动态内存管理 ,new和delete

article/2023/9/24 21:08:56

 

目录

C++动态内存管理

内置类型的动态内存管理

自定义类型的动态内存管理

new和delete的实现原理

new和malloc、delete和free的异同

new的其他用法:定位new


C语言动态内存管理<-点这里

C++动态内存管理

因为C语言中的管理方式使用起来不方便而且有些情况下无法解决问题,C++通过newdelete关键字进行动态内存管理,delete和new必须配套使用,不能new开辟空间使用free释放空间。


内置类型的动态内存管理

//动态申请1个int类型的空间
int* p1 = new int;
delete p1;//动态申请1个int类型的空间并初始化为10
int* p2 = new int(10);
delete p2;//动态申请10个int类型的空间
int* p3 = new int[10];
delete[] p3;//动态申请10个int类型的空间并初始化
int* p4 = new int[10]{1,2,3,4,5,6,7,8,9,10};
delete[] p4;//动态申请一个10行10列的二维数组
//int(*p)[n] 是一个数组指针,该数组有10个int类元素
int(*arr1)[10] = new int[10][10];
delete[] arr1;//用二级指针模拟实现10行10列的二维数组
//内存开辟
int** arr2 = new int*[10];
for (int i = 0;i < 10;i++)
{arr2[i] = new int[10];
}
//空间释放
for (int i = 0;i < 10;i++)
{delete[] arr2[i];
}
delete[] arr2;

申请和释放单个元素的空间使用new和delete,申请和释放连续的空间使用new[]和delete[]


自定义类型的动态内存管理

new为自定义类型分配空间后,会调用构造函数,delete释放自定义类型空间前会调用析构函数

class Stack
{
private:int* _arr;int _capacity;int _top;
public:Stack():_capacity(4),_top(0){_arr = new int[4];}Stack(int capacity):_capacity(capacity),_top(0){_arr = new int[capacity];}~Stack(){delete[] _arr;}
};int main()
{Stack* st1 = new Stack(10);delete st1;Stack* st2 = new Stack[3];delete[] st2;Stack* st3 = new Stack[3]{ 5,2,4 };delete[] st3;Stack* st4 = new Stack[3]{ Stack(5),Stack(2),Stack(4) };delete[] st4;
}

注意:自定义类型数组初始化有多种方法,如果有单参构造函数或者除了缺省参数只有一个参数的构造函数,数组初始化可以直接用该参数类型的值,直接放到{ }内初始化,因为它会自动转换成对象来初始化数组;还可以用匿名对象初始化。


new和delete的实现原理

因为malloc和calloc的功能是开辟空间,如果开辟空间失败返回0。但是对于C++面向对象的语言来说,往往遇到问题要抛异常,所以会用operator new来封装malloc,以达到抛异常的功能。operator delete也是如此。

new的原理
1. 调用operator new函数申请空间
2. 在申请的空间上执行构造函数,完成对象的构造
delete的原理
1. 在空间上执行析构函数,完成对象中资源的清理工作
2. 调用operator delete函数释放对象的空间
new T[N]的原理
1. 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对
象空间的申请
2. 在申请的空间上执行N次构造函数
delete[]的原理
1. 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理
2. 调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释
放空间


new和malloc、delete和free的异同

相同点:new和malloc、delete和free都是从堆上申请空间,都需要对空间手动释放

不同点:

  • (特性)new/delete是关键字,malloc/free是函数
  • (特性)malloc使用时需要计算空间大小,new会根据数据类型自动计算,如果有多个数据直接在[ ]指定数量即可
  • (特性)malloc的返回值是void*,使用时需要强制类型转换,而new不需要。
  • (特性)malloc申请空间失败返回NULL,而new需要捕获异常
  • (功能)malloc申请的空间不会初始化,new申请的空间可以初始化
  • (最重要)(功能)malloc/free只会开辟和释放空间,而new会先调用operator new开辟空间再调用构造函数初始化,delete会先调用析构函数完成空间资源的清理再调用operator delete释放空间。

new的其他用法:定位new

作用:在已经开辟好的一块空间调用构造函数初始化

格式:new(address)custom type(initial list)或者new(address)basic type(initial list)

address是开辟的空间的地址;

custom type表示自定义类型;

initial list表示自定义类型的初始化列表;

basic type表示基本数据类型

使用场景:

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

优势:

内存的申请和释放有一定的开销,遇到需要频繁申请释放内存的情况时,可以一次性开好空间,使用定位new调用构造函数初始化,可以提高效率。

class Date
{friend ostream& operator<<(ostream& _cout, const Date& d);
private:int _year;int _month;int _day;
public:Date(int year = 2023, int month = 1, int day = 1):_year(year),_month(month),_day(day){}~Date(){}
};//流插入运算符重载
ostream&  operator<<(ostream& _cout,const Date& d)
{_cout << d._year << "-" << d._month << "-" << d._day;return _cout;
}int main()
{//基本数据类型int i = 5;int* p1 = (int*)malloc(sizeof(int));new(p1)int(10);cout << *p1 << endl;//10new(p1)int(i);cout << *p1 << endl;//5free(p1);//自定义数据类型Date* p2 = (Date*)malloc(sizeof(Date));new(p2)Date();//无参时,初始化的()可加可不加cout << *p2 << endl;//2023-1-1new(p2)Date(2023, 5, 20);cout << *p2 << endl;//2023-5-20p2->~Date();free(p2);
}


http://www.ngui.cc/article/show-1202705.html

相关文章

2023 华为 Datacom-HCIE 真题题库 09/12--含解析

单项选择题 1.[试题编号&#xff1a;190485] &#xff08;单选题&#xff09;华为交换机MAC地址表的老化时间默认是多少秒? A、500 B、5 C、300 D、400 答案&#xff1a;C 解析&#xff1a;无 2.[试题编号&#xff1a;190484] &#xff08;单选题&#xff09;如图所示&#…

【计算机组成原理与体系结构】硬件系统概述

目录 一、计算机的发展 二、计算机的硬件系统 三、硬件的工作原理 四、计算机系统的层次结构 五、计算机的性能指标 一、计算机的发展 第一代计算机&#xff1a;电子管计算机 第一台电子计算机&#xff1a;ENIAC&#xff08;1946&#xff09; 设计目的&#xff1a;计算导弹…

Ajax请求与浏览器缓存

在现代Web应用程序中&#xff0c;前端代码充斥着大量的Ajax请求&#xff0c;如果对于Ajax请求可以使用浏览器缓存&#xff0c;那么可以显著地减少网络请求&#xff0c;提高程序响应速度。 1. Ajax Request 使用jQuery框架可以很方便的进行Ajax请求&#xff0c;示例代码如下&a…

基础学习——关于list、numpy、torch在float和int等数据类型转换方面的总结

系列文章目录 Numpy学习——创建数组及常规操作&#xff08;数组创建、切片、维度变换、索引、筛选、判断、广播&#xff09; Tensor学习——创建张量及常规操作&#xff08;创建、切片、索引、转换、维度变换、拼接&#xff09; 基础学习——numpy与tensor张量的转换 基础学习…

构建sysbench的镜像

方式1&#xff1a;先docker run一个镜像&#xff0c;手动安装好commit docker run -it --name mycentos arm64v8/centos:7 /bin/bash docker commit -a "PX Bai" mycentos mycentos1 docker run -it -d --namemycentos1 mycentos1 /bin/bash docker exec -it mycent…

每日学术速递6.1

CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 Subjects: cs.CV 1.LayoutGPT: Compositional Visual Planning and Generation with Large Language Models 标题&#xff1a;LayoutGPT&#xff1a;具有大型语言模型的组合视觉规划和生成 作者&…

【MySQL】一文带你了解表的增删改查 CRUD

文章目录 1. 增加&#xff08;Create&#xff09;1.1 单行插入 全列插入1.2 多行插入 指定列插入 2. 查询&#xff08;Retrieve&#xff09;2.1 全列查询2.2 指定列查询2.3 查询字段为表达式2.4 别名2.5 去重2.6 排序 3. 条件查询&#xff08;Where&#xff09;3.1比较运算符…

ChatGLM安装部署问题记录

模型代码网站(国内)&#xff1a;huggingface.co 验证安装环境 python命令行中执行&#xff1a; mypath"C:\\AI\\GLM-CheckPoint\\chatglm-6b-int4" from transformers import AutoTokenizer, AutoModel tokenizer AutoTokenizer.from_pretrained(mypath, trust_r…

【2023】Redis哨兵模式集群

目录 &#x1f3b6; 哨兵模式&#x1f3b6; 搭建哨兵模式集群&#x1f3b6; 搭建一主二从复制集群&#x1f3b6; 创建哨兵节点 &#x1f3b6; 哨兵节点的其他配置&#x1f3b6; 哨兵模式下故障自动恢复效果&#x1f3b6; 通过日志查看故障恢复过程 &#x1f3b6; 哨兵模式 一般…

剑指 Offer 24. 反转链表解题思路

文章目录 题目解题思路 题目 定义一个函数&#xff0c;输入一个链表的头节点&#xff0c;反转该链表并输出反转后链表的头节点。 示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL 限制&#xff1a; 0 < 节点个数 < 5000 …