从零开始学c++——C++动态内存管理

Posted sjp11

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从零开始学c++——C++动态内存管理相关的知识,希望对你有一定的参考价值。

在这里插入图片描述

1.C/C++内存分布

在这里插入图片描述
接下来我们来看一下例子:

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";
 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);
}
  1. 选择题:
    选项: A.栈 B.堆 C.数据段 D.代码段
    globalVar在哪里?____ staticGlobalVar在哪里?____
    staticVar在哪里?____ localVar在哪里?____
    num1 在哪里?____
    char2在哪里?____ *char2在哪里?___
    pChar3在哪里?____ *pChar3在哪里?____
    ptr1在哪里?____ *ptr1在哪里?____

答案:
在这里插入图片描述
解析:因为globalVar是全局变量,staticGlobalVar和staticVar是静态变量,所以它们存储在数据段中,localVar是main函数中的局部变量,num1 是数组名,表示的是数组首元素的地址,为指针变量,也为局部变量,所以它们存储在栈中,
char char2[] = "abcd"表示的意思是将字符串“abcd”拷贝一份存储在char2[]的数组中,所以char2和*char2都表示的是局部变量,都存储在栈中,

在这里插入图片描述

char* pChar3 = "abcd"表示的是将“abcd”的地址储存在pChar3中,所以pChar3是局部变量,而*pChar3是常量字符串,储存在代码段,

在这里插入图片描述
int* ptr1 = (int*)malloc(sizeof (int)*4);表示的是动态开辟一块空间,然后将这块空间的地址存储在ptr1,所以ptr1为局部变量,*ptr1指向动态内存。

2.c++中的动态内存管理

与之前学过的c语言知道,要想申请一块动态内存,我们要使用malloc去向系统申请一块空间,系统就会将这块空间的使用权给你当这块空间不用时,我们在把这块间free掉,也就是这块空间的使用权还给系统。

问题:malloc/calloc/realloc的区别?
malloc会在堆上申请一块动态空间,但这块空间没有初始化,而calloc也会去堆上申请一块空间,但会把这块空间初始化为0,realloc则针对已有的空间进行扩容(有原地扩容和异地扩容)

在这里插入图片描述
而c++中则一般会用new/delete去申请动态空间。

int main()
{
	//申请10个int类型的空间
	int* p1 = (int*)malloc(sizeof(int) * 10);
	int* p2 = new int[10];

	free(p1);
	delete[]p2;

	//申请一个int类型的空间
	int* p3 = (int*)malloc(sizeof(int));
	int* p4 = new int;

	free(p3);
	delete p4;

	return 0;
}

注意:new/delete new[]/delete[]一定要匹配,否则可能会出错。

我们可以看到new类型比malloc操作起来更方便一些,看起来清楚明了,但是难道仅仅只有这些吗,答案是否定的。
在这里插入图片描述
由上图可以见,用new去申请自定义类型的空间,它会去自动调用构造函数初始化,用delete去释放空间,则会去调用析构函数
在这里插入图片描述
如果申请3个ListNode的空间,则会调用3次的构造函数,delete时也会去调用3次析构函数。

3.operator new和operator delete

首先我们得知道new的执行过程它会去调用operator new去申请空间和调用构造函数初始化,delete的执行过程会去调用operator delete去释放空间和析构函数完成对象的资源清理工作
而operator new的底层相当于malloc开空间和抛异常,operator delete的底层相当于free释放空间和抛异常。
什么是抛异常?
抛异常的方法来实现当次执行的程序中断,而不是整个程序全部终止,而断言则会使整个程序终止。

4.什么是内存泄露

申请的空间使用完后没有及时释放,而是指向的那块空间的指针给先销毁掉,导致这块空间没有还给系统,这块空间我们却找不到它,系统不能去重新分配这块空间,但是那块依然存在那里,最终造成内存的浪费。
在这里插入图片描述
内存泄露的危害:长期运行的程序出现内存泄漏,影响很大,如操作系统、后台服务等等,出现内存泄漏会导致响应越来越慢,最终卡死。所以要特别注意及时释放内存。

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

malloc/free,new/delete的共同点都是在堆上申请空间,需要自己释放。
而它们的不同的有:
1.new/delete定义自定义类型会自动调用构造函数和析构函数,而malloc/free不会。
2.new申请空间失败直接抛异常,malloc/f出错返回空指针。
3.new/delete是操作符,malloc/free是函数。
4.malloc申请空间时需要计算空间大小,new只需要在加上空间的类型即可。
5.malloc的返回值为void*, 在使用时必须强转,new不需要,因为new后跟的是空间的类型。

以上是关于从零开始学c++——C++动态内存管理的主要内容,如果未能解决你的问题,请参考以下文章

低价好课:《从零开始学C++》视频教程全集下载百度云高清完整

从零开始学c++——string

从零开始学c++————模板初阶

从零开始学c++——类与对象

从零开始学c++之STL——vector的介绍和使用

从零开始学c++———模拟实现string类(常用接口的实现)