动态持久内存分配
new关键字可以在运行时为基本数据类型、数组和对象分配持久的内存空间。
假如我们想实现一个不改变原数组而返回一个将原数组翻转的函数,如果按照一般的思路,我们写出来的代码是这样的:
#include <iostream> using namespace std; int* reverse(const int* list, int size){ //由于C++中不允许变量作为数组大小,所以暂且设置为6 int result[5]; for (int i = 0, j = size - 1; i < size;i++, j--){ result[i] = list[j]; } return result; } void printArray(const int* list, int size){ for (int i = 0; i < size;i++){ cout << list[i] << " "; } cout << endl; } int main() { int list[5] = {1, 2, 3, 4, 5}; int* p = reverse(list, 5); printArray(p,5); return 0; }
但是运行结果如下:
程序执行了一会返回一个非0数。我们之前说过,因为我们的main函数return 0,所以程序正常结束的话,应该返回0而不是-1073741819。
那么为什么会出现这样的错误呢,因为reverse函数中的result数组是一个局部变量,所以在函数之外访问这个数组的元素是不确定的。因此程序会报错。
那么如何解决呢?这时候就需要使用动态持久内存分配,也就是关键字new了。由于之前的result数组是局部变量,函数结束后就会销毁。所以我们可以用new来使result分配一段持久的内存空间。具体代码是把
int result[5];
换成
int* result = new int[size];
这样以来,就会为result分配一段大小为size*sizeof(int)的内存空间,而且在函数结束之后不会销毁。那么如何释放这段内存呢?我们之后再说,先看程序的运行结果:
符合预期。
释放
delete会显示的释放由new操作符分配的内存空间。
分为两种情况:
1. 释放的是一个指针
delete p;
p是一个由new分配内存的指针。
2. 释放的是一个数组的内存空间
delete [] list;
list是一个由new分配内存数组。
这里要强调一下释放内存的重要性。
看下面的代码:
int* p = new int; *p = 45; p = new int;
上面的代码中,我们没有delete指针p就再次使用new为其分配了新的内存空间。这会使原来p指向的位置无法被访问,也不能够被释放,这种现象叫做内存泄漏。如果这样无法访问的内存空间有很多,那么你计算机的内存会极大的被占用。
每个new操作都应该具有一个delete操作。