目录
四.🚀operator new 与operator delete 函数🚀
6.1✈️malloc/free与new/delete的异同✈️
🚀前言🚀
动态内存管理是C/C++学习中至关重要的一环,C语言中的malloc,realloc,calloc以及free,C++中的new,delete,new[],delete[],都是动态开辟以及释放内存,那么它们之间又有什么区别和联系呢?
一、🚀C/C++内存分布🚀
先来看一下下面这个代码
#include<iostream>
using namespace std;
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);
}
int main()
{
Test();
return 0;
}
1. 选择题:
选项: A.栈 B.堆 C.数据段(静态区) D.代码段(常量区)
globalVar在哪里?____ staticGlobalVar在哪里?____
staticVar在哪里?____ localVar在哪里?____
num1 在哪里?____
char2在哪里?____ *char2在哪里?___
pChar3在哪里?____ *pChar3在哪里?____
ptr1在哪里?____ *ptr1在哪里?____
上面的代码中,可能争议最大的就是*char2的所在区域,这就考验你的C语言学得扎不扎实了,char2是一个数组,而数组是在栈区开辟空间的,那么数组的内容自然也是放在栈区内的。有的小伙伴可能会有这样一个疑惑:“abcd”不是一个字符常量吗?而字符常量不应该放在常量区也就是代码段吗?,没错,你说的是对的,字符常量就是放在代码段的,但是char2是一个数组,char char2[] = "abcd";这条语句其实就相当于将代码段中的字符常量abcd拷贝复制给char2,所以数组中的abcd和代码段中的abcd是两份数据。
2. 填空题:
sizeof(num1) = ____;
sizeof(char2) = ____; strlen(char2) = ____;
sizeof(pChar3) = ____; strlen(pChar3) = ____;
sizeof(ptr1) = ____;
由于上面这几个问题都比较基础,相信也难不倒各位小伙伴,博主在此就不过多赘述,不然就偏离今天的主题了,有不明白的小伙伴可以在评论区留言,博主看到会及时进行回复。
3. sizeof 和 strlen 区别?
- sizeof是一个运算符,strlen是一个字符串函数
- sizeof计算的是整体大小,而strlen计算的是实际大小,这是什么意思呢?看下面这个例子:
int main()
{
char arr[10] = "abcd";
printf("sizeof:%d,strlen:%d\n", sizeof(arr), strlen(arr));
return 0;
}
arr是定义的一个10个字符大小的数组,而数组只用了abcd四个字符进行初始化,sizeof(数组名)计算的是数组大小,strlen计算的是数组内字符串的长度,所以sizeof(arr)应该等于10,strlen等于4
二、🚀C语言中动态内存管理方式🚀
void Test()
{
int* p1 = (int*)malloc(sizeof(int));
free(p1);
// 1.malloc/calloc/realloc的区别是什么?
int* p2 = (int*)calloc(4, sizeof(int));
int* p3 = (int*)realloc(p2, sizeof(int) * 10);
// 这里需要free(p2)吗?
free(p3);
}
面试题:malloc/calloc/realloc的区别?
上面代码中的两个个问题在动态内存管理一篇中博主有详细讲解(链接:http://t.csdnimg.cn/GSM49),不明白的小伙伴可以去考考古哈,由于此篇博客主要讲解C++中的动态内存管理,博主在此就不过多赘述。
三、🚀C++内存管理方式🚀
C语言的动态内存开辟方式在C++中同样可以使用,但是在有些地方又显得无能为力,而且使用起来也比较麻烦,因此C++又提出来自己的管理方式:通过new/delete操作符进行动态内存管理
3.1✈️new/delete操作内置类型✈️
int main()
{
//动态申请一个int型空间
int* ptr1 = new int;
//动态申请一个int型空间并初始化为3
int* ptr2 = new int(3);
//动态申请10个int型空间
int* ptr3 = new int[5];
delete ptr1;
delete ptr2;
delete[] ptr3;
return 0;
}
申请和释放单个元素的空间,使用new和delete;申请和释放连续的空间使用new[]和delete[];
注意:需要匹配起来使用
3.2 ✈️new/delete操作自定义类型✈️
class A
{
public:
A(int a = 0)
: _a(a)
{
cout << "A():" << this << endl;
}
~A()
{
cout << "~A():" << this << endl;
}
private:
int _a;
};
int main()
{
// new/delete 和 malloc/free最大区别是 new/delete对于【自定义类型】除了开空间
//还会调用构造函数和析构函数
A* p1 = (A*)malloc(sizeof(A));
A* p2 = new A(1);
free(p1);
delete p2;
// 内置类型是几乎是一样的
int* p3 = (int*)malloc(sizeof(int)); // C
int* p4 = new int;
free(p3);
delete p4;
A* p5 = (A*)malloc(sizeof(A) * 10);
A* p6 = new A[10];
free(p5);
delete[] p6;
return 0;
}
注意:new在开辟空间时会调用构造函数完成对对象的初始化,delete在释放空间前会调用析构函数完成对空间资源的清理,而malloc/free并不会,这也是new/delete与malloc/free的最大区别
四.🚀operator new 与operator delete 函数🚀
new和delete是用户进行动态内存申请和释放的操作符,operator new 与operator delete 是系统提供的全局函数,new在底层调用operator new全局函数申请空间,delete在底层通过调用operator delete全局函数来释放空间。
其实,operator new实际上也是通过malloc来申请空间的,如果malloc申请空间成功就直接返回,否则执行用户提供的空间不足应对措施,如果用户提供该措施,就继续申请空间,否则就抛异常。operator delete最终也是通过free来释放空间的。
五.🚀new/delete的实现原理🚀
5.1✈️内置类型✈️
如果申请的是内置类型的空间,new和malloc,delete和free,基本上类似,不同点在于:new/delete申请和释放的是单个空间,new[ ]和delete[ ]申请和释放的是连续的空间,而且new在申请空间失败时会抛异常,而malloc是返回一个NULL
5.2✈️自定义类型✈️
- new的原理
1.调用operator new函数申请空间
2.在申请空间上执行构造函数,完成对对象的构造以及初始化
- delete的原理
1.在空间上调用析构函数,完成对象中资源的清理工作
2.调用operator delete函数释放对象的空间
- new T[ ]的原理(T是类型)
1.调用operator new[ ]函数,在operator new[ ]中实际调用operator new函数完成N个对象空间的申请
2.在申请的空间上执行N次构造函数
- delete[ ]的原理
1.在释放的对象空间上调用N次析构函数,完成N个对象中资源的清理
2.调用operator delete[ ]释放空间,实际在operator delete[ ]中调用operator delete来释放空间
六.🚀常见面试题🚀
6.1✈️malloc/free与new/delete的异同✈️
- 相同点
都是在堆上开辟空间,都需要手动释放空间
- 不同点
1.malloc/free是函数,而new/delete是操作符
2.malloc/free不可以初始化,new/delete可以初始化
3.malloc申请空间时需要手动计算大小并传递,new不需要,new只需要在后面跟上类型即可。若是申请多个对象,则只需在[ ]中指定个数即可
4.空间申请失败时,malloc会返回一个NULL,因此malloc使用时必须判空,而new不会,但是new会抛异常
5.malloc申请空间成功后会返回一个void*,使用时必须强转,而new不需要,new只需要在后面跟上类型即可。
6.申请自定义对象时,malloc/free在开辟完空间后,并不会进行初始化,而new在开辟完空间后会调用构造函数完成对对象的初始化,delete在释放空间前会调用析构函数清理资源
6.2✈️内存泄漏✈️
1.什么是内存泄漏?
内存泄漏就是指因为疏忽或是错误造成程序未能释放掉不再使用的内存。内存泄漏并不是指物理上内存的消失,而是指应用程序在分配某段内存后,由于设计错误,导致失去了对该段内存的控制,因而造成了内存的浪费。
2.内存泄漏的危害
长期运行的程序若存在内存泄漏影响会很大,如操作系统,后台服务等等,内存泄漏会导致响应越来越慢,最终卡死。
本篇以C++的动态内存管理为主题的博客到此就要结束了,希望本篇博客可以帮助到各位小伙伴,博主码字不易,如果本篇博客对你有所帮助,还望各位小伙伴点赞👍,收藏⭐+关注,感谢各位的支持!如果有什么不明白的地方或是另有其他的高见,也可以在评论区留言,博主也会及时回复或进行更改,欢迎指正,谢谢!