
内存管理 模版初阶一、内存分布二、new 和 delete二、new 和 delete的实现原理四、定位 new五、模板5.1 函数模板5.1.1函数模板的格式5.1.2函数模板实例化5.1.3函数模板匹配规则5.2 类模板一、内存分布栈区用来存储局部数据。栈区是向下生长的。内存映射段是高效的I/O映射方式用于装载一个共享的动态内存库。用户可使用系统接口创建共享内存做进程间通信。堆区用于动态内存分配。堆区是向上生长的。代码段存储可执行的代码和只读常量。数据段存储全局数据和静态数据。二、new 和 deletenew和delete都是关键字并不是函数。它们的作用是向堆区申请和释放资源。new 和 delete 对于内置类型与malloc / calloc 、free类似但是new 和 delete更加简洁同时能够初始化。(malloc/calloc申请空间失败会返回空指针而new申请空间失败会抛异常)。#includeiostreamusingnamespacestd;voidtest1(){//场景1//申请一个整型类型的空间//以前的写法int*ptr1(int*)malloc(sizeof(int));if(ptr1nullptr){perror(malloc fail);exit(1);}//如果要求同时初始化就应该使用calloc函数但是只能全部初始化为0//释放空间free(ptr1);ptr1nullptr;//新的写法// new 数据类型int*ptr2newint;//如果要求同时初始化// new 数据类型(初始化值)int*ptr3newint(1);//释放空间deleteptr2;deleteptr3;//////////////////////////////////////////////////////////////////////////////////////////////场景2//申请一个连续空间的整型数组//以前写法int*p1(int*)malloc(sizeof(int)*4);if(p1nullptr){perror(malloc fail);exit(1);}//释放空间free(p1);p1nullptr;//新的写法// new 数据类型[数据个数]int*p2newint[4];//如果要求同时初始化// new 数据类型[数据个数] {初始化值}int*p3newint[4]{1,2,3,4};for(inti0;i4;i){cout*(p3i);}coutendl;//释放空间delete[]p2;delete[]p3;}intmain(){test1();return0;}这里要明白new 和 delete的使用方法。同时申请的是连续空间应该使用delete[ ] 进行释放空间保证配套使用。C之所以创建new和delete是为了解决自定义类型。#includeiostreamusingnamespacestd;classA{public:A(int_a0){coutA()endl;}~A(){cout~A()endl;}private:int_a;};voidtest2(){//malloc实现A*ptr1(A*)malloc(sizeof(A));if(ptr1nullptr){perror(malloc fail);exit(1);}//new实现A*ptr2newA;//释放空间free(ptr1);ptr1nullptr;deleteptr2;}可以发现new和delete会自动调用构造函数和析构函数而malloc不会。voidtest(){//支持初始化A*ptr3newA(1);A*ptr6newA(2);//自定义类型的数组A*ptr4newA[2];//自定义类型数组的初始化A*ptr5newA[2]{1,2};delete[]ptr5;//拷贝构造来初始化A*ptr7newA[2]{*ptr3,*ptr6};//匿名对象初始化A*ptr8newA[2]{A(1),A(2)};delete[]ptr8;delete[]ptr7;delete[]ptr4;deleteptr3;deleteptr6;}二、new 和 delete的实现原理new 的实现原理1.调用operator new()函数来实现申请空间资源。operator new()也是通过malloc来实现的但是检查申请空间是否成功并不是看返回的指针是否为nullptr而是通过抛异常来实现的。2.调用析构函数来进行初始化。new[T] 的实现原理1.调用operator new[ ],operator new[ ] 中调用operator new()完成对T个对象空间的申请同时还会在申请空间的初始位置额外开一块空间用来存放T,以便析构时知道析构多少空间返回偏移后的指针。2.调用T次构造函数完成对对象空间的初始化。delete的实现原理1.调用析构函数对自定义类型中的类成员进行空间释放。2.调用operator delete()函数 实现对自定义类型的空间释放。operator delete()也是通过free来释放内存空间的。delete[ ]实现原理1.指针偏移读取到要析构T次然后调用T次析构函数完成对对象空间内申请资源的成员的空间的释放。2.调用operator delete[ ] operator delete[ ] 调用operator delete完成对T个对象空间的释放。四、定位 new定位new是对已经分配好空间的内存调用析构函数进行初始化。格式 new(place_adress)type 或者是 new(place_adress)type(initializer-list)place_adress - 分配空间的地址type - 数据类型initialzer-list 初始化列表常应用于内存池方面。voidtest3(){A*ptr1(A*)malloc(sizeof(A));new(ptr1)A(1);ptr1-~A();free(ptr1);A*ptr2(A*)operatornew(sizeof(A));new(ptr2)A(3);ptr2-~A();operatordelete(ptr2);}重点malloc / free 和 new / delete 的区别malloc申请空间失败返回NULL;new不需要new需要捕获异常。申请自定义类型空间时malloc/free只会开辟和释放空间不会调用构造函数和析构函数。new会在开辟好空间后调用构造函数进行初始化delete会在释放空间之前会调用析构函数对对象内申请资源进行释放。malloc/free 是函数而new / delete是操作符。malloc对申请的空间不会初始化new会对申请的空间进行初始化。malloc返回void类型new后面跟着数据类型会返回该类型的指针。malloc需要手动计算申请空间大小new不需要new后面有数据类型多个对象只需在[ ]内明确对象个数。五、模板模板分为函数模板和类模板。模板不建议声明和定义分离会出现链接错误。5.1 函数模板5.1.1函数模板的格式templatetypename T1,typename T2,……typename Tn 返回类型 函数名参数列表 {}templateclassTvoidswap(constTx,constTy){T tmpx;xy;ytmp;}typename 是关键字意思是类型名也可以用class来代替。T是指数据类型5.1.2函数模板实例化函数模板示例化分为隐式实例化和显式实例化。隐式实例化通过实参编译器来推断数据类型。templateclassTTAdd(constTx,constTy){return(xy);}intmain(){coutAdd(2,3)endl;;//自动推导T类型为intcoutAdd(1.2,3.4)endl;//自动推导T类型为double/* Add(1.2,3); 这样的语句会报错编译器推导不出T的类型到底是int还是double */return0;}显式实例化手动来确定类型。templateclassT1,classT2T2Add(constT1x,constT2y){return(xy);}intmain(){coutAddint,double(1,2.2)endl;return0;}如果实参类型与手动设置类型不一致会进行类型转化如果不能类型转换就会报错。5.1.3函数模板匹配规则1. 非模板函数与函数函数可以以相同名字存在同时也允许模板函数的实例化与非模板函数一致。2. 非模板函数与函数模板实例化后一致那么在调用函数时优先使用非模板函数。如果函数模板能够产生更加匹配的函数那么就会使用函数模板。templateclassT1,classT2T2Add(constT1x,constT2y){return(xy);}doubleAdd(constintx,constdoubley){returnxy;}intmain(){coutAdd(1,2.2)endl;return0;}3.函数模板不会类型转化而普通函数会类型转化。5.2 类模板格式 templatetypename T1,typename T2,……typename Tn class 类名 { //类内成员定义 }类模板实例化需要用指定类型。templateclassTclassStack{public:Stack(intn4){_arrnewT[n];_size0;_capacityn;}~Stack(){delete[]_arr;_arrnullptr;_size_capacity0;}private:T*_arr;int_size;int_capacity;};intmain(){Stackints1;Stackchars2;}