ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

【C++面向对象】12. new/delete 动态分配内存

【C++面向对象】12. new/delete 动态分配内存 文章目录【 0. 内存管理 】【 1. new、delete 】1.1 new 分配内存1.1.1 简单类型1.1.2 检查内存是否分配成功1.2 delete 释放内存【 2. 数组的动态内存分配 】2.1 一维数组2.2 二维数组2.3 三维数组【 3. 对象的动态内存分配 】【 4. 其他内存管理函数 】4.1 malloc() 、free()4.2 memset 内存初始化【 0. 内存管理 】C 程序中的内存分为以下个部分栈区stack函数内部 声明的所有变量默认都占用栈内存由编译器自动分配与释放。存放为运行时函数分配的局部变量、函数参数、返回数据、返回地址等。其操作类似于数据结构中的栈。如声明 int a;系统自动在栈空间中为a开辟空间。堆区heap程序中未使用的内存在程序运行时可用于用户动态分配内存。如C中的malloc以及C中的new如果程序员没有释放程序结束时可能有OS回收。全局区静态区static存放全局变量、静态数据、常量。程序结束后由系统释放。全局区分为已初始化全局区data和未初始化全局区bss。常量区文字常量区存放常量字符串程序结束后由系统释放。代码区存放函数体类成员函数和全局区的二进制代码。实例p1和p2本身是在栈中的但他们指向的地址是堆空间。char*p1(char*)malloc(10);int*p2newint(10);【 1. new、delete 】在 C 中我们可以使用new 运算符为给定类型可以是包括数组在内的任意内置的数据类型也可以是包括类或结构在内的用户自定义的任何数据类型的变量在运行时分配堆内的内存这会返回所分配的空间地址。如果我们不再需要动态分配的内存空间可以使用delete 运算符删除之前由 new 运算符分配的内存。1.1 new 分配内存基本语法newdata-type;1.1.1 简单类型基本语法定义一个指向 指定类型这里指向的是double的指针然后请求内存该内存在执行时被分配double*pvalueNULL;// 初始化为 null 的指针pvaluenewdouble;// 为变量请求内存/*或者*/double*pvaluenewdouble;// 创建1个指针可以指向double类型的变量。实例#includeiostreamusingnamespacestd;intmain(){doublen3.14;double*pvaluenewdouble;//创建1个可以指向double类型的指针pvaluen;// 将指针指向ncout*pvalue;return0;}1.1.2 检查内存是否分配成功如果自由存储区已被用完可能无法成功分配内存所以建议检查 new 运算符是否返回 NULL 指针并采取以下适当的操作double*pvalueNULL;if(!(pvaluenewdouble)){coutError: out of memory.endl;exit(1);}1.2 delete 释放内存在任何时候当我们觉得某个已经动态分配内存的变量不再需要使用时我们可以使用 delete 操作符释放它所占用的内存基本语法deletepvalue;// 释放 pvalue 所指向的内存实例#includeiostreamusingnamespacestd;intmain(){double*pvalueNULL;// 创建1个指向 null 的double类型指针pvaluenewdouble;// 为变量请求内存*pvalue29494.99;// 在分配的地址存储值coutValue of pvalue : *pvalueendl;deletepvalue;// 释放内存return0;}【 2. 数组的动态内存分配 】2.1 一维数组基本语法通过动态内存分配申请一个长度为 n 的数组。int*arraynewint[n]//申请堆内存将指针pvalue指向该内存/* 上面的一行代码可替换为如下 int* array NULL; // 初始化为 null 的指针 array new int[n]; // 申请堆内存将指针array 指向该内存 *///释放内存delete[]array;实例通过动态内存分配 生成一个元素数量为4的一维数组令 a[i]i最后输出数组。#includeiostreamusingnamespacestd;intmain(){intn4;int*anewint[n];//创建1个动态数组afor(inti0;in;i)a[i]i;for(inti0;in;i)couta[i] ;return0;}2.2 二维数组基本语法通过动态内存分配创建一个二维的 mxn 数组。// 动态分配内存int**array;arraynewint*[m];// 上面的两行代码可简化为int **anew int *[m];for(inti0;im;i){array[i]newint[n];}//释放内存for(inti0;im;i){delete[]arrary[i];}delete[]array;实例生成一个3行4列的动态数组令 a[i][j]ij最后输出数组。#includeiostreamusingnamespacestd;intmain(){intm3,n4;// 动态分配内存int**anewint*[m];for(inti0;in;i)a[i]newint[n];// 为数组赋值for(inti0;in;i){for(intj0;jn;j)a[i][j]ij;}// 输出数组for(inti0;in;i){for(intj0;jn;j){couta[i][j];if(jn-1)coutendl;elsecout ;}}//释放申请的堆内存for(i0;im;i){delete[]a[i];}delete[]a;return0;}2.3 三维数组基本语法通过动态内存分配创建一个三维的 mxnxh 数组。// 动态分配内存int***array;arraynewint**[m];for(inti0;im;i){array[i]newint*[n];for(intj0;jn;j){array[i][j]newint[h];}}//释放内存for(inti0;im;i){for(intj0;jn;j){delete[]array[i][j];}delete[]array[i];}delete[]array;实例#includeiostreamusingnamespacestd;intmain(){inti,j,k;// p[2][3][4]int***p;pnewint**[2];for(i0;i2;i){p[i]newint*[3];for(j0;j3;j)p[i][j]newint[4];}//输出 p[i][j][k] 三维数据for(i0;i2;i){for(j0;j3;j){for(k0;k4;k){p[i][j][k]ijk;coutp[i][j][k] ;}coutendl;}coutendl;}// 释放内存for(i0;im;i){for(j0;jn;j){delete[]p[i][j];}delete[]p[i];}delete[]p;return0;}【 3. 对象的动态内存分配 】对象的动态内存分配与简单的数据类型类似。实例为一个包含四个 Box 对象的数组分配内存构造函数将被调用 4 次同样地当删除这些对象时析构函数也将被调用相同的次数4次。#includeiostreamusingnamespacestd;classBox{public:Box(){cout调用构造函数endl;}~Box(){cout调用析构函数endl;}};intmain(){Box*myBoxArraynewBox[4];delete[]myBoxArray;// 删除数组return0;}【 4. 其他内存管理函数 】4.1 malloc() 、free()头文件C#include stdlib.hC #include cstdlibmalloc() 函数从堆heap中分配一块指定大小的内存区域并返回一个指向这块内存的指针。malloc 分配的内存不会被自动初始化它包含未定义的值。基本语法size需要分配的内存大小以字节为单位。成功时返回指向分配内存的指针 void* 类型使用时通常需要进行类型转换。失败时返回 NULL 或 nullptr在 C11 及以后版本中。void*malloc(size_t size);free() 函数释放 指针 指向的存储空间被释放的空间通常被送入可用存储区池。使用 malloc 分配的内存必须使用 free 函数 来释放不能使用 C 的 delete 运算符。释放内存后将指针设置为 NULL 是一个好习惯可以防止野指针问题。基本语法ptr指向要释放的内存的指针。无返回值。voidfree(void*ptr);例程int*array(int*)malloc(10*sizeof(int));// 申请1个足够存储10个整数的内存free(array);//释放该内存malloc/free 和 new/delete 对比在 C 语言中的malloc() 函数在 C 中仍然存在但建议尽量不要使用 malloc() 函数。malloc/freenew/deletemalloc/free 是C/C的标准库函数new/delete是C的运算符malloc申请的堆区内存不会初始化new是内存自动初始化malloc需要用户计算好字节数来申请空间new自动计算分配空间malloc函数返回值是void*在使用时需要进行类型强制转换在 new 后面直接写明类型malloc申请内存失败会返回一个NULL在使用的时候必须进行判空new申请内存失败后会抛出异常对于自定义数据类型malloc/free只开辟空间没有初始化不会调用构造/析构函数对于自定义数据类型new不只是分配了内存它还创建了对象。申请、销毁时会触发构造/析构函数。malloc/free 都是程序员手动从 堆区 申请然后手动释放new/delete都是程序员手动从 堆区 申请然后手动释放实例#includeiostream#includecstdlib// 包含malloc函数的头文件usingnamespacestd;intmain(){// 分配足够存储10个整数的内存int*array(int*)malloc(10*sizeof(int));// 检查分配是否成功if(arrayNULL){// 如果分配失败处理错误return-1;}// 使用分配的内存for(inti0;i10;i){array[i]i*i;// 初始化数组元素}// 打印数组元素for(inti0;i10;i){coutarray[i] array[i]endl;}// 释放分配的内存free(array);// 注意只能使用free来释放malloc分配的内存return0;}4.2 memset 内存初始化头文件C#include string.hC#include stringmemset()函数是 C 语言标准库中的一个函数用于将一块内存区域的前 n 个字节中的每个字节设置为指定的值。基本语法ptr指向要填充的内存块的指针。value要设置的值通常是一个介于0 到 255之间的整数因为 memset 一次只设置一个字节大小。num要设置的字节数。返回指向大小为 num 内存块的原始指针 ptr如果错误发生返回NULL。void*memset(void*ptr,intvalue,size_t num);实例#includestdio.h#includestring.h// 包含 memset 函数的头文件intmain(){charbuffer[5];// 声明一个足够大的字符数组// 使用 memset 初始化 buffer 的前 5 个字节为 6memset(buffer,6,5);// 打印printf(Initialized buffer with 6:\n);for(inti0;i5;i){printf(%c ,buffer[i]);}return0;}
返回列表