【C++初阶】内存管理

目录

一.C语言中的动态内存管理方式

二.C++中的内存管理方式 

1.new/delete操作内置类型 

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

3.浅识抛异常 (内存申请失败)

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

三.new和delete的实现原理 

1.内置类型 

2.自定义类型 


一.C语言中的动态内存管理方式

void Test()
{
	int* p1 = (int*)malloc(sizeof(int));
	free(p1);

	// 1.malloc/calloc/realloc的区别是什么?
	int* p2 = (int*)calloc(4, sizeof(int));
	int* p3 = (int*)realloc(p2, sizeof(int) * 10);

	// 这里需要free(p2)吗?
	free(p3);
}

答:不需要,realloc分为原地扩容和异地扩容,原地扩容的话返回一个指针,所以p3和p2是相等的;异地扩容的话会将原来的空间自动free掉。

二.C++中的内存管理方式 

C语言内存管理方式在C++中可以继续使用,但有些地方就无能为力,而且使用起来比较麻烦,因 此C++又提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理。 

1.new/delete操作内置类型 

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

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

	// 动态申请10个int类型的空间
	int* ptr6 = new int[3];

	delete ptr4;
	delete ptr5;
	delete[] ptr6;
}

 

 注意:申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用 new[]和delete[],注意:匹配起来使用

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

  •  C语言写法建立结点
struct ListNode* CreateListNode(int val)
{
	struct ListNode* newnode = (struct ListNode*)malloc(sizeof(struct ListNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return NULL;
	}

	newnode->_next = NULL;
	newnode->_val = val;
	return newnode;
}
  • C++建立结点 
struct ListNode
{
	ListNode* _next;
	int _val;

	ListNode(int val)
		:_next(nullptr)
		,_val(val)
	{}
};
int main()
{
	
	//自定义类型,开空间+构造函数;new失败了以后抛异常,不需要手动检查
	ListNode* node1 = new ListNode(1);
	ListNode* node2 = new ListNode(2);
	ListNode* node3 = new ListNode(3);
	

	return 0;
}
  • C++手撕一个链表 
// 创建的不带哨兵位
ListNode* CreateList(int n)
{
	ListNode head(-1);  // 哨兵位

	ListNode* tail = &head;
	int val;
	printf("请依次输入%d个节点的值:>", n);
	for (size_t i = 0; i < n; i++)
	{
		cin >> val;
		tail->_next = new ListNode(val);
		tail = tail->_next;
	}

	return head._next;
}
int main()
{
	ListNode* list1 = CreateList(5);
	return 0;
}

3.浅识抛异常 (内存申请失败)

void func()
{
	int n = 1;
	while (1)
	{
		int* p = new int[1024 * 1024 * 100];
	
		cout << n << "->" << p << endl;
		++n;
	}
}
int main()
{
	func();
	return 0;
}

  • C语言内存申请失败 

对比发现C语言申请失败返回0需要检查,而C++不需要检查,直接抛异常。 

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

class A
{
public:
	A(int a = 0)
		: _a(a)
	{
		cout << "A():" << this << endl;
	}

	~A()
	{
		cout << "~A():" << this << endl;
	}
private:
	int _a;
};

class Stack
{
public:
	Stack()
	{
		_a = (int*)malloc(sizeof(int) * 4);
		_top = 0;
		_capacity = 4;
	}

	~Stack()
	{
		free(_a);
		_top = _capacity = 0;
	}
private:
	int* _a;
	int _top;
	int _capacity;
};

int main()
{
	//int* p1 = (int*)operator new(10 * 4);

	A* ptr1 = new A;  // operator new + 1次构造
	A* ptr2 = new A[10]; // operator new[] + 10次构造

	//cout << sizeof(A) << endl;
	delete ptr1; // 1次析构 + operator delete
	delete[] ptr2; // 10次析构 + operator delete[]

	Stack* pst = new Stack;
	delete pst;

	int* p1 = new int[10];

	return 0;
}

注意:在申请自定义类型的空间时,new会调用构造函数,delete会调用析构函数(先掉析构函数再释放内存),而malloc与 free不会。 

三.new和delete的实现原理 

1.内置类型 

如果申请的是内置类型的空间,new和malloc,delete和free基本类似,不同的地方是: new/delete申请和释放的是单个元素的空间,new[]和delete[]申请的是连续空间,而且new在申请空间失败时会抛异常,malloc会返回NULL。 

2.自定义类型 

 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来释 放空间

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

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

相关文章

电机应用-正点原子直流有刷电机例程笔记

目录 基础驱动实验&#xff1a;调速和换向 初始化工作 电机基础驱动API 电压、电流、温度检测实验 初始化工作 采集工作 编码器测速实验 编码器接口计数原理 初始化工作 编码器测速工作 速度环控制实现 PID相关函数 PID运算 电流环控制实现 PID相关函数 PID运算…

代码随想录算法训练营第三十三天|1005.K次取反后最大化的数组和、134. 加油站、135. 分发糖果

1005.K次取反后最大化的数组和 刷题https://leetcode.cn/problems/maximize-sum-of-array-after-k-negations/description/文章讲解https://programmercarl.com/1005.K%E6%AC%A1%E5%8F%96%E5%8F%8D%E5%90%8E%E6%9C%80%E5%A4%A7%E5%8C%96%E7%9A%84%E6%95%B0%E7%BB%84%E5%92%8C.…

iOS-设置指定边圆角(左上、左下等)

以UILabel举例&#xff0c;效果图如下&#xff1a; 代码如下&#xff1a; //设置左上与右下圆角&#xff08;可自行编辑指定圆角位置&#xff09; UIBezierPath *maskPath [UIBezierPath bezierPathWithRoundedRect:_sleepStateLabel.bounds byRoundingCorners:UIRectCornerT…

Python 全栈系列227 部署chatglm3-API接口

说明 上一篇介绍了基于算力租用的方式部署chatglm3, 见文章&#xff1b;本篇接着看如何使用API方式进行使用。 内容 1 官方接口 详情可见接口调用文档 调用有两种方式&#xff0c;SDK包和Http。一般来说&#xff0c;用SDK会省事一些。 以下是Python SDK包的git项目地址 安…

“环波罗的海”包围圈将正式形成

据“直新闻”的消息称&#xff0c;近日匈牙利国会同意了瑞典加入北约的申请&#xff0c;在走完相关后续程序后&#xff0c;瑞典就将成为北约第三十二个成员国&#xff0c;而北约对俄罗斯打造的“环波罗的海”包围圈也将正式形成&#xff0c;即除俄方外&#xff0c;波罗的海周边…

JEECG_ExcelExportServer批量数据导出超过60000条

项目上线了,结果导出数据时发现只能导出6w条,好奇怪啊... 本地试了试结果每次都卡在10w条. orz 开始扒拉批量导出 ExcelBatchExportServer server new ExcelBatchExportServer();server.init(exportParams,TTransLine.class);server.write(exportList);Workbook workbook s…

github如果给第三方项目提PR(Pull Request)

参考&#xff1a; https://blog.csdn.net/Leventcoco/article/details/135871779 1&#xff09;第一步 先fork第三方项目 点击fork然后就同步一份到自己名下了&#xff0c;后续修改在自己名下这项目上先修改&#xff1a; 2&#xff09;修改项目&#xff08;要提交的新功能或…

阿里云幻兽帕鲁服务器怎么续费?阿里云服务器租用价格优惠有哪些?

阿里云幻兽帕鲁服务器的续费可以通过登录阿里云账户&#xff0c;访问ECS控制台页面来进行。首先&#xff0c;需要在控制台中找到想要续费的幻兽帕鲁服务器实例。接着&#xff0c;在控制台页面左侧导航栏中找到“费用中心”&#xff0c;点击进入&#xff0c;在费用中心页面中找到…

一个Web3项目的收官之作,必然是友好的用户界面(Web3项目三实战之四)

正如标题所述,一个对用户体验友好的应用,总是会赢得用户大加赞赏,这是毋庸置疑的。 甭管是web2,亦或是已悄然而至的Web3,能有一个外观优美、用户体验效果佳的的界面,那么,这个应用无疑是个成功的案例。 诚然,Web3项目虽然核心是智能合约攥写,但用户界面也是一个DApp不…

WSL2外部网络设置

1 关闭所有WSL系统 wsl --shutdown 2 打开Hyper-V管理器 3 将“虚拟交换机管理器”-> ”WSL连接类型“设置为“外部网络” 4 启动WSL系统&#xff0c;手动修改WSL网络 将WSL网络IP修改为192.168.1.9 sudo ip addr del $(ip addr show eth0 | grep inet\b | awk {print $2} |…

前端monorepo大仓共享复杂业务组件最佳实践

一、背景 在 Monorepo 大仓模式中&#xff0c;我们把组件放在共享目录下&#xff0c;就能通过源码引入的方式实现组件共享。越来越多的应用愿意走进大仓&#xff0c;正是为了享受这种组件复用模式带来的开发便利。这种方式可以满足大部分代码复用的诉求&#xff0c;但对于复杂…

C++基于多设计模式下的同步异步日志系统day2

&#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;C基于多设计模式下的同步&异步日志系统 &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 主要内容实现了日志代码设计的实…

【详识JAVA语言】方法签名

方法签名 在同一个作用域中不能定义两个相同名称的标识符。比如&#xff1a;方法中不能定义两个名字一样的变量&#xff0c;那为什么类中就可以定义方法名相同的方法呢&#xff1f; 方法签名即&#xff1a;经过编译器编译修改过之后方法最终的名字。具体方式&#xff1a; 方…

python3.x的在线与离线安装纯净版

由于计划搭建一套使用python自动分析日志的流程&#xff0c;发现我们的测试环境CentOS 7仍然没有安装python3&#xff0c;无法使用这些新的库。Python 3在设计上着重提升了语言的一致性和易用性&#xff0c;它引入了许多关键改进&#xff0c;此外&#xff0c;Python 3环境拥有丰…

Javaweb之SpringBootWeb案例之自动配置以及常见方案的详细解析

3.2 自动配置 我们讲解了SpringBoot当中起步依赖的原理&#xff0c;就是Maven的依赖传递。接下来我们解析下自动配置的原理&#xff0c;我们要分析自动配置的原理&#xff0c;首先要知道什么是自动配置。 3.2.1 概述 SpringBoot的自动配置就是当Spring容器启动后&#xff0c…

项目-SERVER模块-Buffer模块

Buffer模块 一、Buffer模块是什么&#xff1f;实现思想是什么&#xff1f;二、代码实现如何设计&#xff1a;1.成员变量&#xff1a;2.构造函数&#xff1a;3.获取地址和空间大小4.读写偏移向后移动5.扩容函数6.写入函数7.读取函数8.获取地址和空间大小9.获取地址和空间大小10.…

springboot自写插件封包

在Spring Boot中自写插件或封包&#xff08;通常指的是创建自定义的starter&#xff09;是一种常见的做法&#xff0c;用于将一系列相关的配置和组件打包成一个独立的模块&#xff0c;从而简化依赖管理和配置过程。以下是一个简单的步骤&#xff0c;指导你如何创建一个自定义的…

如何高效管理项目:从规划到执行

导语&#xff1a;项目管理是一项复杂而重要的工作&#xff0c;涉及多个方面&#xff0c;包括规划、执行、监控和收尾。本文将介绍如何高效管理项目&#xff0c;从规划到执行&#xff0c;帮助您成功完成项目目标。 一、项目规划 项目规划是项目成功的关键。在规划阶段&#xff0…

JVM原理-基础篇

Java虚拟机&#xff08;JVM, Java Virtual Machine&#xff09;是运行Java应用程序的核心组件&#xff0c;它是一个抽象化的计算机系统模型&#xff0c;为Java字节码提供运行环境。JVM的主要功能包括&#xff1a;类加载机制、内存管理、垃圾回收、指令解释与执行、异常处理与安…

[每周一更]-(第89期):开源许可证介绍

开源代码本就是一种共享精神&#xff0c;一种大无畏行为&#xff0c;为了发扬代码的魅力&#xff0c;创造更多的价值&#xff0c;让爱传递四方&#xff0c;让知识惠及更多人&#xff1b; 写文章也是一种共享精神&#xff0c;让知识传播出去。 介绍下开源中不同许可证的内容限…