C/C++内存管理

C/C++内存管理

1. C/C++内存分布

首先,我们要了解几个概念。
(1).栈又叫堆栈,由编译器自动分配释放 ,非静态局部变量/存放函数的参数值等等。其操作方式类似于数据结构中的栈。栈是向下增长的。
(2).内存映射段是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口创建共享共享内存,做进程间通信。
(3).堆,一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 ,用于程序运行时动态内存分配,堆是可以上增长的。
(4).数据段(静态区),存储全局数据静态数据
(5).代码段,可执行的代码/只读常量
Alt

int globalVar = 1;			//全局变量
static int staticGlobalVar = 1;		//静态成员变量
void Test()
{
	static int staticVar = 1;		//静态成员变量
	int localVar = 1;		//函数栈帧里的局部变量	
	int num1[10] = { 1, 2, 3, 4 };		//大小为40字节的数组
	char char2[] = "abcd";		//字符数组
	char* pChar3 = "abcd";		//指向一个常量的字符指针
	int* ptr1 = (int*)malloc(sizeof(int) * 4);	//动态开辟,只开空间
	int* ptr2 = (int*)calloc(4, sizeof(int));   //动态开辟,开空间,并初始化为0
	int* ptr3 = (int*)realloc(ptr2, sizeof(int) * 4);	//扩容
	free(ptr1);
	free(ptr3);
}	

对应上面的概念,我们就可以知道它们所储存的位置。
globalVar、staticGlobalVar、staticVar 储存在数据段上,localVar 、num1、char2、*char2、pChar3、ptr1储存在栈上,*pChar3、储存在代码段上,*ptr1为ptr1指针指向的内容,为动态开辟,在堆上。

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

malloc/calloc/realloc和free
(1)malloc函数:用于申请一块连续的指定大小的内存块区域以void*类型返回分配的内存区域地址,当无法知道内存具体位置的时候,想要绑定真正的内存空间,就需要用到动态的分配内存。
在这里插入图片描述
(2).calloc函数:在内存的动态存储区中分配n个长度为size的连续空间,函数返回一个指向分配起始地址的指针;如果分配不成功,返回NULL。

(3).realloc函数:先判断当前的指针是否有足够的连续空间,如果有,扩大mem_address指向的地址,并且将mem_address返回,如果空间不够,先按照newsize指定的大小分配空间,将原有数据从头到尾拷贝到新分配的内存区域,而后释放原来mem_address所指内存区域(注意:原来指针是自动释放,不需要使用free),同时返回新分配的内存区域的首地址。即重新分配存储器块的地址。
在这里插入图片描述

注:calloc和malloc的区别在:calloc在动态分配完内存后,自动初始化该内存空间为零,而malloc不初始化,里边数据是随机的垃圾数据。

3. C++中动态内存管理

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

对于内置类型:

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

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

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

	delete ptr1;
	delete ptr2;
	delete[] ptr3;
}

在这里插入图片描述

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

对于自定义类型:


void test2()
{
	// 申请单个A类型的对象
	A* a3 = new A;
	delete a3;
	
	// 申请10个A类型的对象
	A* a4 = new A[10];
	delete[] a3;
}

在申请自定义类型的空间时,new会调用构造函数,delete会调用析构函数,而malloc,free不会。
在这里插入图片描述
在这里插入图片描述

4. operator new与operator delete函数

new和delete是用户进行动态内存申请和释放的操作符,operator new 和operator delete是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间。

operator new: 该函数实际通过malloc来申请空间,当malloc申请空间成功时直接返回;申请空间失败,尝试 执行空 间不足应对措施,如果改应对措施用户设置了,则继续申请,否则抛异常。
operator delete: 该函数最终是通过free来释放空间的

5. new和delete的实现原理

对于内置类型来说:

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

对于自定义类型来说:

new的原理:

  1. 调用operator new函数申请空间
  2. 在申请的空间上执行构造函数,完成对象的构造。

delete的原理:

  1. 在空间上执行析构函数,完成对象中资源的清理工作
  2. 调用operator delete函数释放对象的空间

注:new T[N] 是申请N个对象的空间,并N次调用构造函数, delete[] 是执行N次析构函数,完成N个对象中资源的清理,再释放空间。

总结:
new :开空间 + 初始化(构造)
delete : 析构 +释放

6. 定位new表达式(placement-new)

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

void test() 
{
     // pt现在指向的只不过是与A对象相同大小的一段空间,还不能算是一个对象,因为构造函数没有执行
 	A* pt = (A*)malloc(sizeof(A));

	new(pt) Test; // 注意:如果Test类的构造函数有参数时,此处需要传参 
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值