C++之内存管理 |
您所在的位置:网站首页 › new和malloc的用法 › C++之内存管理 |
文章目录
前言一、C/C++内存分配1.C/C++中内存区域划分图2.说明3.堆和栈的区别1.区别2.总结
4.实例
二、C语言中的动态内存管理方式三、C++中动态内存管理方式1.new/delate操作内置类型2.new/delete操作自定义类型
四、new和delete的实现原理1.内置类型2.自定义类型1.new的原理2.delete的原理3.new T[N]的原理4.delete[] 的原理
五、new/delete和malloc/free的区别1.用法功能2.底层
六、内存泄漏1.什么是内存泄漏?内存泄漏的危害?2.内存泄漏的分类?(了解)3.内存泄漏如何检测?(了解)4.内存泄漏如何避免?(了解)
总结
前言
本文主要介绍关于C++中的内存管理的相关概念。 一、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"; 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); } 1. 选择题: 选项 : A.栈 B.堆 C.数据段(静态区) D.代码段(常量区) globalVar在哪里?____ staticGlobalVar在哪里?____ staticVar在哪里?____ localVar在哪里?____ num1 在哪里?____ char2在哪里?____ *char2在哪里?___ pChar3在哪里?____ *pChar3在哪里?____ ptr1在哪里?____ *ptr1在哪里?____ 2. 填空题: sizeof(num1) = ____; sizeof(char2) = ____; strlen(char2) = ____; sizeof(pChar3) = ____; strlen(pChar3) = ____; sizeof(ptr1) = ____; 3. sizeof 和 strlen 区别?该程序中各个数据对应的虚拟进程地址空间如图: 使用malloc/calloc/realloc这三个函数进行动态内存管理。 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的区别是什么? malloc:在堆上申请一块指定大小的空间,返回指向该空间首地址的指针,不进行其他操作; calloc:在堆上申请一块指定大小的空间,同时将这个空间的内容全部初始化为0,返回指向该空间首地址的指针; realloc:在malloc/calloc已经申请好空间后,对该空间进一步扩容。如果原来空间的后续空间足够就原地调整/扩容,不改变空间的首地址;如果原来空间的后续空间不够就异地调整/扩容,将原来空间的内容拷贝过去,同时释放原来的空间,返回新空间的首地址。当然,如果没有原来的空间,即传给realloc的指针是NULL时,那么它的使用和malloc是一样的,返回指向该空间首地址的指针。上面代码中的p2需要释放吗? 答:不需要,因为realloc是对p2的空间进行重新调整后得到p3,(如果后续空间足够,就;如果后续空间不够,就异地调整,)只需要释放p3就可以了。 三、C++中动态内存管理方式首先,C语言中的动态内存管理在C++中可以继续使用,但是有一些地方不太方便,因此C++提出了自己的内存管理方式:通过new/delete操作符进行动态内存管理。 申请空间:new; 释放空间:delete。 1.new/delate操作内置类型使用实例: void Test() { // 相较于C种的malloc/calloc等,除了用法没有别的区别 // 动态申请一个int类型的空间 int* ptr4 = new int; // 动态申请一个int类型的空间并初始化为10 int* ptr5 = new int(10); // 动态申请3个int类型的空间 int* ptr6 = new int[3]; delete ptr4; delete ptr5; delete[] ptr6; }注意:申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用new[]和delete[],要匹配起来使用。 2.new/delete操作自定义类型使用实例: class A { public: A(int a = 0) : _a(a) { cout // new/delete 和 malloc/free最大区别是new/delete对于【自定义类型】除了开空间,还会调用构造函数(初始化)和析构函数(清理空间) A* p1 = (A*)malloc(sizeof(A)); A* p2 = new A(1); free(p1);//要配套使用,不能malloc出来的空间用delete释放,也不能new出来的空间用free释放 delete p2; A* p5 = (A*)malloc(sizeof(A)* 10); A* p6 = new A[10]; free(p5); delete[] p6;//new出来多个对象,必须要用delete[]来释放 return 0; }注意: malloc/calloc/realloc与free配套使用; A* p1 = new A(1) 与 delete p1 配套使用; A* p2 = new A[10] 与 delete[] p2 配套使用。 如果不配套使用可能会出现各种错误。 因为malloc/calloc/realloc与free它们和new与delete的实现不同(取决于编译器),一次性new多个对象就要用delete[]进行释放。 在VS2013的环境下,编译器对delete[]的识别如下图所示: 如果申请的是内置类型的空间,new和malloc,delete和free基本类似。 不同的地方是:new/delete申请和释放的是单个元素的空间,new[]和delete[]申请的是连续空间,而且new在申请空间失败时会抛异常,malloc会返回NULL。 2.自定义类型 1.new的原理 调用operator new函数申请空间(operator new函数不是new的运算符重载,他是一个C++官方库定义的全局函数,它是通过对malloc函数进行封装,进行申请空间。封装malloc函数的原因:当申请空间失败时会抛异常,更符合C++的机制);在申请的空间上执行构造函数,完成对象的构造。 2.delete的原理 在空间上执行析构函数,完成对象中资源的清理工作;调用operator delete进行释放空间(operator delete不是delete的运算符重载,它是由C++官方库定义的全局函数,它是通过对free函数的封装,进行释放空间。封装free函数的原因:当释放空间失败时会抛异常,更符合C++的机制) 3.new T[N]的原理 调用operator new[]函数申请空间,在operator new[]中,实际调用operator new函数完成N个对象空间的申请在申请的空间上执行N次构造函数。 4.delete[] 的原理 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理; 2.调用operator delete[]释放空间,实际上在operator delete[]中调用operator delete来释放空间。 五、new/delete和malloc/free的区别malloc/free和new/delete的共同点是:都是从堆上申请空间,并且需要用户手动释放。 不同点是: 1.用法功能 new/delete是操作符,malloc/free是函数,使用方法不同;new不用手动计算空间大小,只需要在后面跟上对象的类型,如果是多个对象在[]中写上对象的个数即可(编译器会自动推算),malloc需要手动计算要开辟的空间大小;malloc的返回值为void*,返回值要进行强转,new不需要,new后跟的是空间的类型;malloc如果返回值为NULL则说明空间开辟失败,因此使用时要判空,new不需要,但是new需要捕获异常。 2.底层 malloc申请的空间不会进行初始化,new会进行初始化(指的是自定义类型);申请自定义类型对象时,malloc/free只会开辟/释放空间,不会调用构造函数/析构函数,new/delete会调用构造函数/析构函数,申请空间后调用构造函数完成对象的初始化,释放空间前调用析构函数完成对象的资源清理工作。 六、内存泄漏 1.什么是内存泄漏?内存泄漏的危害?内存泄漏:内存泄漏指因为疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并不是指内存在物理上的消失,而是应用程序分配某段内存后,因为设计错误,失去了对该段内存的控制(即,空间还在,但指向空间的指针丢失了,导致找不到这块空间),因而造成了内存的浪费。 内存泄漏的危害:长期运行的程序出现内存泄漏,影响很大,如操作系统、后台服务等等,出现内存泄漏会导致响应越来越慢,最终卡死。 2.内存泄漏的分类?(了解)C/C++程序中一般我们关心两种方面的内存泄漏: 堆内存泄漏(Heap leak) 通过malloc / calloc / realloc / new等从堆中分配的一 块内存,用完后没有被释放。系统资源泄漏 程序使用系统分配的资源,比方套接字、文件描述符、管道等没有使用对应的函数释放掉,导致系统资源的浪费,严重可导致系统效能减少,系统执行不稳定 3.内存泄漏如何检测?(了解)第三方内存泄漏检测工具。 4.内存泄漏如何避免?(了解) 养成一种良好的编程习惯,申请的内存空间记着匹配的去释放。使用智能指针(后期会介绍) 总结以上就是今天要讲的内容,本文介绍了C++中的内存管理的相关概念。本文作者目前也是正在学习C++相关的知识,如果文章中的内容有错误或者不严谨的部分,欢迎大家在评论区指出,也欢迎大家在评论区提问、交流。 最后,如果本篇文章对你有所启发的话,希望可以多多支持作者,谢谢大家! |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |