从零开始学C++ (内存管理)

1.C/C++内存分布

C/C++中内存主要分为:栈、堆、数据段、代码段、内存映射段。

  1. 栈:又叫堆栈,存放非静态局部变量,函数的参数,返回值、栈是向下增长的。

  2. 堆:用于程序运行时动态分配。

  3. 数据段:存放全局变量,静态变量。

  4. 代码段:存放可执行的代码和常量。

  5. **内存映射段:**是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口

    创建共享共享内存,做进程间通信。

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

C语言中主要使用malloc,calloc,realloc和free来进行动态内存管理,那么malloc,calloc,realloc有什么区别呢?

1.函数原型与参数不同

  • mallocvoid* malloc(size_t size);

    • 只接收1个 参数:要分配的总字节数
  • callocvoid* calloc(size_t nmemb, size_t size);

    • 接收2个 参数:元素个数单个元素大小 。实际分配的总字节数为 nmemb * size
  • reallocvoid* realloc(void *ptr, size_t new_size);

    • 接收2个 参数:原先的内存指针新的总字节数。它用于调整已存在内存块的大小。

2.初始化行为不同

  • malloc不会初始化 内存。分配的内存中存储的是残留的"脏数据"(随机值)。如果你需要清零,必须手动调用 memset

  • calloc会初始化为 0 。分配完成后,它会将内存块中的所有字节全部置为 0(保证数据安全)。

  • realloc不会初始化新增的部分 。它只负责调整大小,原有的数据内容会被保留 (如果缩小,缩掉的部分丢失;如果扩大,新增加的空间不会清零,同样是脏数据)。

3.C++内存管理

C++使用new和delete来进行动态内存管理

1.new和delete用于内置类型

cpp 复制代码
	//动态申请一个int 类型的空间
	int* p1 = new int;
	//动态申请一个int 类型的空间并初始化为10
	int* p2 = new int(10);
	//动态申请是个int 类型的空间
	int* p3 = new int[10];

	delete p1;
	delete p2;
	delete[] p3;

注意,申请单个空间用new和delete,申请连续空间用new\[\]和delete\[\],要搭配使用。

2.new和delete用于自定义类型

cpp 复制代码
class A
{
public:
	A(int a = 0)
		: _a(a)
	{
		cout << "A():" << this << endl;
	}
	~A()
	{
		cout << "~A():" << this << endl;
	}
private:
		int _a;
};


int main() {

	//new和delete与malloc和free对内置类型的处理几乎没有区别,但对自定义类型,new和delete会调用构造函数和析构函数,malloc和free不调用
	A* p1 = (A*)malloc(sizeof(A));
	A* p2 = new A(10);

	free(p1);
	delete p2;

	int* p3 = (int*)malloc(sizeof(int)); // C
	int* p4 = new int;

	free(p3);
	delete p4;


	A* p5 = (A*)malloc(sizeof(A) * 10);
	A* p6 = new A[10];
	free(p5);
	delete[] p6;
	return 0;
}

4.operator newoperator delete****函数

new和delete操作符在底层实际上是调用operator new与operator delete两个全局函数,operator new也是通过malloc来申请空间,申请成功就直接返回,否则就执行用户提供的空间不足应对措施,如果用户提供就继续申请,否则就抛异常,operator delete通过free来释放空间。

5.new和delete的实现原理

1.内置类型

对于内置类型,new和delete与malloc和free基本类似,不同在于new和delete申请和释放的是单个空间,new\[\]和delete\[\]申请和释放的是连续空间,new申请失败会抛异常,malloc申请失败会返回NULL。

2.自定义类型

new和delete

new:

  1. 调用operator new完成空间的申请
  2. 调用构造函数,完成对对象的初始化构造

delete:

  1. 调用析构函数,完成对对象资源空间的清理
  2. 调用operator delete完成空间的释放

new\[\]和delete\[\]

new\[\]:

  1. 调用operator new\[\],实际上operator new\[\]调用operator new完成N次空间的申请
  2. 调用N次构造函数,完成对对象的初始化构造

delete\[\]:

  1. 调用N次析构函数,完成对对象资源空间的清理
  2. 调用operator delete\[\],operator delete\[\]调用operator delete完成N次空间的释放
相关推荐
Tisfy2 小时前
LeetCode 1927.求和游戏:抵消+看最值
java·leetcode·游戏·题解·博弈论
「QT(C++)开发工程师」7 小时前
C++ 11 常用for循环
开发语言·c++
我还记得那天7 小时前
0 初识C++
开发语言·c++
秋饼8 小时前
JDK 27 企业级 AI 服务落地实战:G1 默认、紧凑对象头、后量子 TLS 与 JFR 脱敏全解析
java·ai·技术分享·后端开发
卓怡学长9 小时前
w176基于SpringBoot的医院管理系统
java·spring boot·spring·maven·intellij-idea
lemon_sjdk9 小时前
ObjectProperty
java·开发语言·算法
hh9509 小时前
Agent Plan x DeepSeek Harness:Agent 供应链安全与第三方插件审计
java·开发语言·安全·agent plan·adg成都社区·adg社区
吴声子夜歌9 小时前
Java面试——HBase原理及应用
java·面试·hbase
浪兎兎9 小时前
【Java Web】Servlet + JSP 笔记
java·前端·servlet