【C++】内存管理

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

在讲解C++的内存管理方式之前,我们先简单复习一下C语言的动态内存管理方式。

C++的内存分配方式与C相同,一般都分为六块区域:内核空间(用户代码不能读写),栈,内存映射段,堆,数据段,代码段。

其中要注意的部分为:

  1. 栈又叫堆栈--非静态局部变量/函数参数/返回值等等,栈是向下增长的。

  2. 堆用于程序运行时动态内存分配,堆是可以上增长的。

  3. 数据段--存储全局数据和静态数据。

4.代码段--可执行的代码/只读常量。

简略介绍完了C/C++中程序内存区域划分的方式,我们再进入主题:C语言的动态内存管理方式。

相信大家在学习C++之前都学习过C语言,知晓C语言的动态内存管理方式主要由四个函数完成:malloc/calloc/realloc/free。

简略介绍的话,malloc是用来分配一块指定大小的内存区域。calloc的用法与malloc相近,与malloc不同的是它在分配完内存区域后还会对其进行初始化。而realloc一般是用来更改之前分配的内存区域的大小,可以是增加或减少。当然,如果一开始扩容的区域不存在,realloc也可以当作malloc来使用。

C++内存管理方式

在复习完了C语言的内存管理方式之后,我们来学习C++的内存管理方式。

C语言内存管理方式在C++中可以继续使用,但有许多地方存在不便。C++有自己的内存管理方式,即通过new和delete操作符进行动态内存管理。

接下来是这两个操作符使用的示范:

下面是普通的申请情况

复制代码
#include <iostream>

using namespace std;

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

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

	//动态申请5个int类型的空间
	int* p3 = new int[5];

	//动态申请5个int类型的空间并初始化(未赋值的地方为0)
	int* p4 = new int[5] {1,2,3};

	delete p1;
	delete p2;
	delete[] p3;
	delete[] p4;
	return 0;
}

还有一些特殊的情况,如构造自定义类型的数组(构造单个自定义类型如上面示例演示一样):

复制代码
#include <iostream>

using namespace std;

class A
{
public:
	A(int n, int m)
		:_a1(n)
		, _a2(m)
	{

	}
private:
	int _a1;
	int _a2;
};

int main()
{
	//这里只介绍比较特殊便捷的方法
	//普通的构造方法就不过多赘述

	//1.使用匿名对象构造
	A* p1 = new A[3]{ A(1,1),A(2,2),A(3,3) };

	//2.使用隐式类型转换构造
	A* p2 = new A[3]{ {1,1},{2,2},{3,3} };

	delete[] p1;
	delete[] p2;
	return 0;
}

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

new[]和delete[],需要匹配起来使用!

可能有些人就会好奇:如果不匹配使用会如何呢?

如果进行不匹配使用,有些情况可能不会出错,但有些情况就会出现内存泄漏导致程序崩溃,所以保险起见还是进行匹配使用为好。

operator new 和 operator delete 函数

由上面的介绍我们可知:new和delete是用户进行动态内存申请和释放的操作符。而它们是通过调用operator new和operator delelete来实现的相关操作的。

那么什么是operator new函数 和 operator delete函数呢?

operator new 和operator delete是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间。

这些概念听起来很"高大上",但实际上,这两个函数的底层是通过malloc和free来实现的:

通过上述两个全局函数的实现我们知道,operator new 实际也是通过malloc来申请空间,如果malloc申请空间成功就直接返回,否则执行用户提供的空间不足应对措施,如果用户提供该措施就继续申请,否则就抛异常。而且operator delete 最终是通过free来释放空间的

malloc/free和new/delete的区别

malloc/free和new/delete的共同点是:都是从堆上申请空间,并且需要用户手动释放。

不同的地方是:

  1. malloc和free是函数,new和delete是操作符

  2. malloc申请的空间不会初始化,new可以初始化

  3. malloc申请空间时,需要手动计算空间大小并传递,new只需在其后跟上空间的类型即可,如果是多个对象,[]中指定对象个数即可

  4. malloc的返回值为void*, 在使用时必须强转,new不需要,因为new后跟的是空间的类型

  5. malloc申请空间失败时,返回的是NULL,因此使用时必须判空,new不需要,但是new需

要捕获异常

  1. 申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理释放

它们的核心区别为第六点,即自定义类型用new/delete能自动调用构造函数和析构函数。

这六点区别,前四点为用法区别,后两点为本质区别。

定位new

定位new表达式是在已分配的原始内存空间中调用构造函数初始化一个对象。用来显式调用构造函数

复制代码
//显式调用构造函数(要通过定位new实现)
A* p2 = (A*)operator new(sizeof(A));
new(p2)A(1);
//析构函数可以直接调用,不需要通过定位new

简单来说,定位new就是用来给一个已分配空间的变量进行初始化

它的应用场景为:内存池(从堆中划分出一块区域专供使用)

但因为想这块区域申请只能得到内存,而构造函数需要自己调用,所以有了定位new这个概念(这部分仅做了解即可)

相关推荐
DARLING Zero two♡2 小时前
【计算机网络】简学深悟启示录:序列化&&反序列化
开发语言·计算机网络·php
ID_180079054732 小时前
乐天(Letian)商品详情API接口的调用示例与代码实现
开发语言·python
水饺编程2 小时前
第4章,[标签 Win32] :绘制信息结构
c语言·c++·windows·visual studio
WBluuue2 小时前
AtCoder Beginner Contest 441(ABCDEF)
c++·算法
一位搞嵌入式的 genius2 小时前
深入理解 JavaScript 原型与继承:从基础到进阶
开发语言·前端·javascript
晨非辰2 小时前
C++波澜壮阔40年|类和对象篇:拷贝构造与赋值重载的演进与实现
运维·开发语言·c++·人工智能·后端·python·深度学习
hetao17338372 小时前
2026-01-16~19 hetao1733837 的刷题笔记
c++·笔记·算法
m0_719084112 小时前
滴滴滴滴滴
java·开发语言
董世昌412 小时前
深度解析var、let、const的区别与最佳使用场景
开发语言·前端·javascript