C++---动态内存管理

C/C++内存分布
在这里插入图片描述
栈:存储非静态局部变量、函数参数、返回值。
内存映射段:动态库。
堆:程序运行时动态内存分配。
数据段:存储全局变量、静态数据。
代码段:可执行代码,只读常量。

C语言中动态内存管理

  • malloc函数

  • void* malloc(size_t number)

  • 在堆中动态申请一块长度为numbre个字节的连续区域,返回该区域的首地址,但是返回类型为void* ,在使用时需要对其进行类型转换,并且该块区域没有进行初始化,如果想对其进行整体初始化,可以结合memset函数对其进行初始化操作。

  • void memeset(void* buf,int c,int count) ,buff为该区域的首地址,c为初始化的值,count为区域的大小。

  • 注意 malloc申请空间时,有可能会失败,所以在使用malloc申请出来的空间,需要对其进行判空操作。

  • calloc函数

  • void* calloc(size_t number,size_t size)

  • number为申请空间的元素个数,size为每个元素大小,用calloc申请空间的总大小为number*size。

  • calloc在申请空间时,默认对其区域进行初始化操作,默认初始化的值为0。

    扫描二维码关注公众号,回复: 12745138 查看本文章
  • 注意 calloc申请空间时,有可能会失败,所以在使用calloc申请出来的空间,需要对其进行判空操作。

  • realloc函数

  • void* realloc(void* buff,size_t new_size)

  • realloc对malloc申请的空间调整其大小,buff为空间的首地址,new_size为将原空间大小调整到。new_size可以比原空间大,也可以比原空间小。

  • 注意 realloc申请空间时,有可能会失败,所以在使用realloc申请出来的空间,需要对其进行判空操作。

  • malloc/calloc/realloc区别

  • malloca函数对申请到的空间不能进行初始化,calloc会对申请的空间同时进行初始化。calloc会将指针类型初始化为空指针,数据类型初始化为0。realloc如果对内存缩小,缩小的一部分数据会丢失,当其对内存扩大时,编译器会先在其原本内存的后面进行扩展,如果位置不足,则会重新开辟一块内存空间,最终进行数据的搬移,返回的指针很可能是一个新的地址。

  • 不论是用上面哪个函数申请空间,申请的空间都用free释放。void free(void* buff),buff为申请空间的首地址。用free释放完空间后,需要手动将原空间的首地址赋值为NULL,避免出现野指针。

C++内存管理操作

  • new / delete 申请内置类型
void TestFunc()
{
    
    
	int* p1 = new int; //申请int类型的空间;
	int* p2 = new int(3); //申请一个int类型的空间并对其初始化为3;
	int* p3 = new int[3]; //申请3个int类型的空间,相当于申请int类型的数组
}
  • 申请自定义类型
class Date
{
    
    
public:
	Date()
	{
    
    	
		cout<<"Date()构造函数"<<endl;
	}
	~Date()
	{
    
    
		cout<<"~Date()析构函数"<<endl;
	}
private: 
	int d;
};
void TestFunc()
{
    
    
	//malloc申请1个自定义类型的空间
	Date* p1 = (Date*)malloc(sizeof(Date));
	free(p1);
	//new申请一个自定义类型的空间
	Date* p2 = new Date;
	delete p2;
}

在这里插入图片描述
在申请空间上忙new申请的空间会调用构造函数,malloc只会申请出一个空间,delete会调用析构函数,free不会。

注意 :在申请空间与释放空间时,new与delete,malloc与free必须成对出现。否则会出现错误。

new[]/delete[]

  • new[]同时申请多个空间,delete[]同时对多个空间进行释放。
int* p1 = new int[10]; //申请10个int型空间
delete[] p1;
Date* p2 = new Date[10]; //申请10个自定义类型空间
delete[] p2; 

new底层实现原理

new申请空间会进行两步操作,第一步是申请空间,第二步为调用构造函数进行初始化操作。

  • 第一步:申请空间,底层代码
void* operator new(size_t size)
{
    
    
	//底层调用malloc函数循环申请空间
	malloc循环申请空间;
	if(申请失败)
		提供空间不足的措施;
	else
		直接退出;
}
  • 第二步:调用构造函数完成初始化操作。

delete底层原理

  • void operator delete()。
  • 第一步调用析构函数,释放对象中的资源
  • 在释放对象资源结束前最后一句,调用free()函数,释放对象空间。

operator new 实际也是通过malloc来申请空间,如果malloc申请空间成功就直接返回,否则执行用户提供的空间不足应对措施,如果用户提供该措施就继续申请,否则就抛异常。operator delete最终是通过free来释放空间。

new[ ]底层原理

  • void* operator new[](size_t size) 内部调用void* operator new(size_t size)函数。
  • 调用operator new[]函数,在operator new[]中实际调用operator new函数完成对多个对象空间的申请。
  • 在申请空间上执行多次构造函数。

delete[ ]底层原理

  • void operator delete[]
  • 调用多次析构函数,完成多个对象的资源清理工作。
  • 执行operator delete[]释放空间,实际上是调用operator delete函数来释放空间。

猜你喜欢

转载自blog.csdn.net/qq_42708024/article/details/104295898