【C++】内存管理
以Date类为类:代码语言:javascriptAI代码解释class Datepublic:~Date()private:int main()delete pd;return 0;在这里插入图片描述申请连续空间并初始化:代码语言:javascriptAI代码解释class Datepublic:~Date()private:int main()return 0;代码语言:javascriptAI
一、C/C++内存分布
我们先来看下面的一段代码和相关问题:
代码语言:javascript
AI代码解释
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);
}
问题:

在这里插入图片描述
解答:

在这里插入图片描述

在这里插入图片描述
二、C语言内存管理方式
对于C语言中的内存管理方式可参考:【C语言中动态内存管理】,有助于我们在偏底层一点的了解C++内存管理方式。
三、C++内存管理方式
C语言内存管理方式在C++中可以继续使用,但有些地方就无能为力,而且使用起来比较麻烦,因此C++又提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理。
3.1 new/delete操作内置类型
代码语言:javascript
AI代码解释
void Test()
{
// 动态申请一个int类型的空间
int* ptr1 = new int;
// 动态申请一个int类型的空间并初始化为10
int* ptr2 = new int(10);
// 动态申请10个int类型的空间
int* ptr3 = new int[3];
// 动态申请10个int类型的空间并初始化
int* ptr4 = new int[3] {1,2,3};
delete ptr1;
delete ptr2;
delete[] ptr3;
delete[] ptr4;
}
调试结果:

在这里插入图片描述

在这里插入图片描述
注意:申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用new[]和delete[],注意:匹配起来使用。
可能对于内置类型的操作并没有显著的区别,接下来,我们来看一下new和delete操作自定义类型吧。
3.2 new和delete操作自定义类型
以Date类为类:
代码语言:javascript
AI代码解释
class Date
{
public:
Date(int year = 2025, int month = 9, int day = 9)
{
std::cout << "Date(int year = 2025, int month = 9, int day = 9)" << std::endl;
}
~Date()
{
std::cout << "~Date()" << std::endl;
}
private:
int _year = 2024;
int _month = 1;
int _day = 1;
};
int main()
{
Date* pd = new Date;
delete pd;
return 0;
}

在这里插入图片描述
申请连续空间并初始化:
代码语言:javascript
AI代码解释
class Date
{
public:
Date(int year = 2025, int month = 9, int day = 9)
{
std::cout << "Date(int year = 2025, int month = 9, int day = 9)" << std::endl;
}
~Date()
{
std::cout << "~Date()" << std::endl;
}
private:
int _year = 2024;
int _month = 1;
int _day = 1;
};
int main()
{
Date* pd = new Date[2]{ {1,1,1},{2,2,2} };
delete[] pd;
return 0;
}
对于这段代码,我们来强调一个点,也算是对类和对象的复习:
代码语言:javascript
AI代码解释
// 严格按C++标准分析(不考虑编译器优化):
Date* pd = new Date[2]{ {1,1,1},{2,2,2} };
// 这行代码的执行过程:
// 1. 调用operator new[]分配容纳2个Date对象的连续内存空间
// 2. 对于数组中的每个元素:
// a. 首先用初始化列表 {1,1,1} 构造临时Date对象(调用普通构造函数)
// Date temp1(1, 1, 1);
// b. 然后用临时对象拷贝构造数组第一个元素(调用拷贝构造函数)
// new(pd) Date(temp1);
// c. 销毁临时对象(调用析构函数)
// temp1.~Date();
//
// d. 用初始化列表 {2,2,2} 构造临时Date对象(调用普通构造函数)
// Date temp2(2, 2, 2);
// e. 然后用临时对象拷贝构造数组第二个元素(调用拷贝构造函数)
// new(pd+1) Date(temp2);
// f. 销毁临时对象(调用析构函数)
// temp2.~Date();
在这里,已经看得很明白了: new/delete 和 malloc/free最大区别是 new/delete对于【自定义类型】除了开空间还会调用构造函数和析构函数。 对于内置类型前面说过,是几乎是一样的。
所以可以看出: 在申请自定义类型的空间时,new会调用构造函数,delete会调用析构函数,而malloc与free不会。
四、operator new与operator delete函数
new和delete是用户进行动态内存申请和释放的操作符,operator new 和operator delete是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间。 我们将会从底层两者的实现来进行了解
4.1 operator new
operator new:该函数实际通过malloc来申请空间,当malloc申请空间成功时直接返回;申请空间失败,尝试执行空间不足应对措施,如果改应对措施用户设置了,则继续申请,否则抛异常(后续会针对抛异常单独写篇文章),现在我们只需知道如果申请内存失败了,这里会抛异常。
更多推荐

所有评论(0)