C/C++内存管理相关知识点

1.内存分布

C/C++将内存大体上分为四个区域:栈区、堆区、静态区(数据段)、常量区(代码段)。

栈区:用来存储函数调用时的临时信息的结构,存放为运行时函数分配的局部变量、函数参数、返回数据、返回地址等。

堆区:程序员自己使用malloc或new自己申请出来存的地方。(动态内存分配)

静态区: static修饰的数据,全局数据,存放的位置。

常量区:不会改变的常量,存在这里。


看下面一段代码,回答问题:

int globalVar = 1;
static int staticGlobalVar = 1;
void Test()
{
    
    
 static int staticVar = 1;
 int localVar = 1;
 int num1[10] = {
    
     1, 2, 3, 4 };
 char char2[] = "abcd";
 const char* pChar3 = "abcd";
 int* ptr1 = (int*)malloc(sizeof(int) * 4);
 int* ptr2 = (int*)calloc(4, sizeof(int));
 int* ptr3 = (int*)realloc(ptr2, sizeof(int) * 4);
 free(ptr1);
 free(ptr3);
}

看上面一段代码,请回答如下:

在这里插入图片描述
在这里插入图片描述

2. new/delete关键字

2.1 操作内置类型

int main()
{
    
    

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

	// 动态申请5个int 类型的空间
	int* ptr3 = new int[5];
	delete[] ptr3;         // 释放ptr3,注意怎么new的怎么delete

	 动态申请5个int 类型的空间,并初始化
	int* ptr4 = new int[5]{
    
     1,2,3 };
	delete[] ptr4;		   // 释放ptr4,注意怎么new的怎么delete

	return 0;
}

**注意:new 对应 delete,new [] 对应 delete [] 。**不可用错。

操作自定义类型

new 和 delete 除了申请和释放空间外,会自动调用构造函数和析构函数。

class A
{
    
    
public:
	A(int a = 0)
	{
    
    
		cout << "A()" << endl;
	}
	~A()
	{
    
    
		cout << "~A()" << endl;
	}

private:
	int _day;
	int _year;
	int _month;
};

int main()
{
    
    
	A* p1 = new A(1);  //一次构造
	delete p1;			//一次析构

	A* p2 = new A[5];  // 五次构造
	delete[] p2;       //五次析构

	

	return 0;
}

3. opeartor new 与 operator delete函数

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

其中:
operator new:该函数实际通过malloc来申请空间,申请成功直接返回;失败时,尝试执行空间不足应对策略,如果用户对该措施设置了,继续申请空间,否则抛异常。

operator delete:该函数最终是通过free()来释放空间的。


在这里插入图片描述
通过该定义也可以看出,free()其实也是一个重命名,真正的函数名是后面的。

4. new 和 delete 原理

4.1 内置类型

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

4.2 自定义类型

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

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

  • newT[N] 原理
    1.调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对象空间的申请。
    2.在申请的空间上执行N次构造函数

  • delete[] 原理
    1.在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理。
    2.调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释放空间

如下例子总结:
在这里插入图片描述

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

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

使用语法:
new (place_address) type 或者new (place_address) type(initializer-list)
place_address必须是一个指针,initializer-list是类型的初始化列表。


new(p1)A;    //如果A的构造函数有参数,此处需要传参
nwe(p2)A(10);  // 初始化参数为10

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

共同点:
都是从堆上申请空间,并需要手动释放。

不同点:

  1. malloc和free是函数,new和delete是关键字。
  2. malloc申请的空间不会初始化,new可以调用构造函数完成初始化。
  3. malloc申请空间时,需要手动计算空间大小并传递,new只需在其后面跟上空间的类型即可,如果是多个对象,[]中指定个数即可。
  4. malloc返回值是void*,在使用时必须强转,new不需要,因为new后面跟的是空间类型。
  5. malloc申请空间失败时,返回的是NULL,因此使用时必须判空,new不需要,但是需要捕获异常。
  6. 申请自定义类型时,malloc/free 只会开辟空间,不会调用构造函数与析构函数,而new在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成对象空间中资源的清理。

7. 内存泄漏

相关知识后续会继续补充。。。

猜你喜欢

转载自blog.csdn.net/weixin_45153969/article/details/132909867