C++--内存管理

35 篇文章 0 订阅

1. C/C++内存分布

在这里插入图片描述

  • 栈(堆栈):非静态局部变量/函数参数/返回值等,栈是向下增长的。
  • 内存映射段:高效的I/O映射方式,用于装载一个共享的动态内存库。
  • 堆:用于程序运行时动态内存分配,堆是向上增长的。
  • 参数在栈空间存放,malloc或new申请的空间为堆区.

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

· malloc/calloc/realloc和free

  • malloc:只申请空间,空间内容为随机值,不初始化;
  • calloc:申请空间,空间全部初始化为0。
  • realloc:重新申请空间,不初始化;
void test()
{
	//malloc只申请空间,空间内容为随机值,不初始化
	char* ptr1 = (char*)malloc(sizeof(char));
	//调整空间大小
	char* ptr2 = (char*)realloc(ptr1, 2 * sizeof(char));
	//申请新的空间,功能和malloc相同,不初始化
	char* ptr3 = (char*)realloc(NULL, sizeof(char));
	
	//ptr1的空间不能显式释放(会导致二次释放)
	//只能显式释放realloc返回之后的空间,传入realloc中的指针空间不能显式释放
	free(ptr2);
	free(ptr3);
	//申请空间+空间全部初始化为0
	char* ptr4 = (char*)calloc(4, sizeof(char));
}
	free(ptr4);

3. C++内存管理方式

  • C++内存管理方式:通过new和delete操作符进行动态内存管理。

· new/delete操作内置类型

  • 申请和释放单个元素的空间,使用new和delete操作符;
  • 申请和释放连续的空间,使用new[]和delete[]。
void test()
{
	//申请和释放的方式保持一致
	int* mptr = (int*)malloc(sizeof(int));
	free(mptr);
	//类型指针  指针变量 = new 类型
	//类型指针  指针变量 = new 类型(初始值)
	//类型指针  指针变量 = new 类型(元素个数)
	int* ptr = new int;
	delete ptr;
	//申请空间+初始化  初始值为10-->4字节
	int* ptr2 = new int(10);
	delete ptr2;
	//连续空间  包含10个元素-->内容为随机值
	int* arr = new int(10);
	//释放连续空间
	delete[] arr;
}

· new/delete操作自定义类型

  • 在申请在定义类型的空间时,new会调用构造函数,delete会调用析构函数,而malloc与free不会。
    在这里插入图片描述
class A
{
public:
	A()
	{
		cout << "A()" << endl;
	}
	A(int a)
		:_a(a)
	{}
	A(int a,int b,int c)
		:_a(a)
	{}
	~A()
	{
		cout << "~A()" << endl;
	}
private:
	int _a = 10;
};
void test()
{
	A* mpa = (A*)malloc(sizeof(A));
	free(mpa);
	cout << "------" << endl;
	//自定义类型:new:申请空间+调用构造函数进行空间内容的初始化
	//类型指针 指针变量 = new 类型 -->调用默认构造函数(无参、全缺省)
	A* pa1 = new A;
	//类型指针 指针变量 = new 类型(参数列表)-->调用带参构造
	A* pa2 = new A(10);
	A* pa3 = new A(1, 2, 3);
	//自定义类型:delete:调用析构完成资源清理+空间释放
	delete pa1;
	delete pa2;
	delete pa3;
	//自定义类型:连续空间
	//不能使用带参的构造函数进行多个对象的空间申请和初始化
	//new[]:申请空间+调用N次构造函数,需要有默认构造
	A* arrA = new A[3];
	//delete[]: 调用N次析构+空间释放
	delete[] arrA;
}

4. operator new与operator delete函数

  • 不是运算符重载函数,是系统提供的全局函数;
  • new在底层调用operator new全局函数来申请空间;operator new是通过malloc来申请空间的。
  • delete在底层通过operator delete全局函数来释放空间;(封装free,不会抛异常);operator delete是通过free来释放空间的。
  • 内置类型
void test()
{
	//内置类型
	//new: operator new --> malloc
	int* ptr = new int;
	//delete: operator delete --> free
	delete ptr;
	//new[]: operator new[] --> operator new --> malloc
	int* ptr2 = new int[];
	//delete[]: operator delete[] --> operator delete -->free
	delete[] ptr2;
}
  • 自定义类型
class A
{
public:
	A(int a=10)
		:_a(a)
	{}
private:
	int _a;
};
void test()
{
	//自定义类型
	//new:operator new --> malloc -->构造
	A* pa = new A;
	//delete:析构--> operator delete --> free
	delete pa;
	//new[]: operator new[] --> operator new --> malloc --> N次构造
	A* pa2 = new A[10];
	//delete[]: N次析构 --> operator delete[] --> operator delete -->free
	delete[] pa2;
}

5. new和delete的实现原理

· 内置类型

  • new和malloc,delete和free基本相似;
  • 不同点是new / delete申请/释放的是单个元素的空间,new[] / delete[]申请/释放的是连续空间,而且new在申请空间失败时会抛异常。

· 自定义类型

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

6. malloc/free和new/delete的区别

相同点

  • 都是从堆上申请空间,并且需要手动释放。

不同点

  • malloc和free是函数,new和delete是操作符;
  • malloc申请的空间不会初始化,new可以初始化;
  • malloc申请空间时,需要手动计算空间大小并传递,new只需要在其后跟上空间的类型即可;
  • malloc的返回值时void* ,在使用时必须强转,new不需要,new后面跟的是空间的类型;
  • malloc申请空间失败时,返回的时NULL,因此必须判空,new不需要,只需要捕获异常;
  • 申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数和析构函数,而new在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理。

7. 内存泄漏

  • 内存泄漏的危害:
    · 长期运行的程序出现内存泄漏会导致响应越来越慢,最终卡死。
  • 内存泄漏分类
    · 堆内存泄漏(Heap leak):若分配的内存没有被释放,以后这部分空间就不能再被使用,就会产生Heap leak。
    · 系统资源泄漏:指程序使用系统分配的资源,没有使用对应的函数释放掉,导致系统资源浪费,严重可导致系统效能减少,系统执行不稳定。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值