C++ new / delete 关键字
使用 new 关键字可以动态分配内存,而 delete 关键字可以删除由 new 关键字分配的内存
动态内存
想成为一名合格的 C++ 开发者,必须知道动态内存在 C++ 中是如何工作的
C++ 程序中的内存分为两个部分:
- 栈: 在函数内部声明的所有变量都将占用栈内存
- 堆: 这是程序中未使用的内存,在程序运行时可用于动态分配内存
在日常的开发中,我们经常碰到提前预知需要多少内存来存储某个定义变量中的特定信息,因为所需内存的大小需要在运行时才能确定。
在 C++ 中,我们可以使用 new 运算符为给定类型的变量在运行时分配堆内的内存,然后返回所分配的空间地址
一旦不需要动态分配的内存,可以使用 delete 运算符来删除由 new 运算符分配的内存
new 和 delete 运算符
new 运算符可以为任意的数据类型动态分配内存。
new 运算符的语法格式如下
new data-type;
- data-type 可以是包括数组在内的任意内置的数据类型,也可以是包括类或结构在内的用户自定义的任何数据类型。
比如我们需要定义一个指向 double 类型的指针,然后请求内存,该内存在执行时被分配。
我们可以按照下面的语句使用 new 运算符来完成这点
double* pvalue = NULL; // 初始化为 null 的指针 pvalue = new double; // 为变量请求内存
最佳实战
-
如果自由存储区已被用完,可能无法成功分配内存。 所以建议检查 new 运算符是否返回 NULL 指针,并采取以下适当的操作
double* pvalue = NULL; if( !(pvalue = new double )) { cout << "Error: out of memory." <<endl; exit(1); }
-
在任何时候,当我们觉得某个已经动态分配内存的变量不再需要使用时,请使用 delete 操作符释放它所占用的内存,如下所示:
delete pvalue; // 释放 pvalue 所指向的内存
范例:如何使用 new 和 delete 运算符
/** * file: main.cpp * author: 简单教程(www.twle.cn) * * Copyright © 2015-2065 www.twle.cn. All rights reserved. */ #include <iostream> using namespace std; int main () { double* pvalue = NULL; // 初始化为 null 的指针 pvalue = new double; // 为变量请求内存 *pvalue = 3.1415926; // 在分配的地址存储值 cout << "Value of pvalue : " << *pvalue << endl; delete pvalue; // 释放内存 return 0; }
编译运行以上范例,输出结果如下
$ g++ main.cpp && ./a.out Value of pvalue : 3.14159
动态分配数组的内存
我们可以使用 new 关键字给一个字符数组动态分配内存。
比如我们给一个长度为 20 的字符数组动态分配内存,语句如下:
char* pvalue = NULL; // 初始化为 null 的指针 pvalue = new char[20]; // 为变量请求内存
如果要删除我们刚才创建的数组,语句如下:
delete []pvalue; // 删除 pvalue 所指向的数组
1. 给一维数组动态分配内存
可以使用 new or delete 关键字给一维数组动态分配内存或删除它们,语句如下:
int *array=new int [m]; // 动态分配,数组长度为 m delete [] array; //释放内存
2. 给二维数组动态分配内存
使用 new or delete 关键字给二维数组动态分配内存或删除它们,语句如下:
int **array // 假定数组第一维长度为 m, 第二维长度为 n // 动态分配空间 array = new int *[m]; for( int i=0; i<m; i++ ) { array[i] = new int [n] ; } //释放 for( int i=0; i<m; i++ ) { delete [] arrar[i]; } delete [] array;
范例:动态分配二维数组内存
/** * file: main.cpp * author: 简单教程(www.twle.cn) * * Copyright © 2015-2065 www.twle.cn. All rights reserved. */ #include <iostream> using namespace std; int main() { int **p; int i,j; //p[4][8] //开始分配4行8列的二维数据 p = new int *[4]; for(i=0;i<4;i++){ p[i]=new int [8]; } for(i=0; i<4; i++){ for(j=0; j<8; j++){ p[i][j] = j*i; } } //打印数据 for(i=0; i<4; i++){ for(j=0; j<8; j++) { if(j==0) cout<<endl; cout<<p[i][j]<<"\t"; } } //开始释放申请的堆 for(i=0; i<4; i++){ delete [] p[i]; } delete [] p; return 0; }
3. 给三维数组动态分配内存
int ***array; // 假定数组第一维为 m, 第二维为 n, 第三维为h // 动态分配空间 array = new int **[m]; for( int i=0; i<m; i++ ) { array[i] = new int *[n]; for( int j=0; j<n; j++ ) { array[i][j] = new int [h]; } } //释放 for( int i=0; i<m; i++ ) { for( int j=0; j<n; j++ ) { delete array[i][j]; } delete array[i]; } delete [] array;
范例 : 给三维数组动态分配内存
/** * file: main.cpp * author: 简单教程(www.twle.cn) * * Copyright © 2015-2065 www.twle.cn. All rights reserved. */ #include <iostream> using namespace std; int main() { int i,j,k; // p[2][3][4] int ***p; p = new int **[2]; for(i=0; i<2; i++) { p[i]=new int *[3]; for(j=0; j<3; j++) p[i][j]=new int[4]; } //输出 p[i][j][k] 三维数据 for(i=0; i<2; i++) { for(j=0; j<3; j++) { for(k=0;k<4;k++) { p[i][j][k]=i+j+k; cout<<p[i][j][k]<<" "; } cout<<endl; } cout<<endl; } // 释放内存 for(i=0; i<2; i++) { for(j=0; j<3; j++) { delete [] p[i][j]; } } for(i=0; i<2; i++) { delete [] p[i]; } delete [] p; return 0; }
动态分配对象的内存
给对象动态分配内存与给简单的数据类型没有什么不同。
比如,下面的代码,使用一个对象数组来理清这一概念
/** * file: main.cpp * author: 简单教程(www.twle.cn) * * Copyright © 2015-2065 www.twle.cn. All rights reserved. */ #include <iostream> using namespace std; class Box { public: Box() { cout << "调用构造函数!" <<endl; } ~Box() { cout << "调用析构函数!" <<endl; } }; int main( ) { Box* myBoxArray = new Box[4]; delete [] myBoxArray; // 删除数组 return 0; }
编译运行以上范例,输出结果如下:
调用构造函数! 调用构造函数! 调用构造函数! 调用构造函数! 调用析构函数! 调用析构函数! 调用析构函数! 调用析构函数!