【C++】细说C++中的数组之动态数组
【fishing-pan:https://blog.csdn.net/u013921430转载请注明出处】
1. 前言
上周,写了一篇《细说C++中的数组之静态数组》,今天讲述一下动态数组。
数组是一种顺序存储的数据结构,在定义数组时,首先要确定数组的大小。静态数组在编译时就需要确定数组的大小,所以,为了防止内存溢出,我们尽量将数组定义的大一些,但是这样太过浪费内存。
动态数组则不同,它不需要在编译时就确定大小,它的大小在程序运行过程中确定,所以可以根据程序需要而灵活的分配数组的大小,相比静态数组,它更“灵活”、“自由”。但是动态数组需要进行显式的内存释放。
2. 动态数组内存分配
动态数组进行内存分配的格式为new T[size],size可以不是常量表达式;如下面的例子所示。
int size = 10; //此处的size不是常量表达式。
int* Dynamic_Arr2 = new int[size]; //未初始化
可以看出,虽然我们分配了一个动态数组,其实返回的是一个T类型的指针,指针指向的是数组的第一个元素,从这个角度来说,动态数组更像是指针。也是由于这种性质,导致了动态数组中size可以取0,即返回一个空指针,即分配一个空动态数组是合法的。同样的道理,返回的是一个指针,那么就不能使用begin或者end迭代器进行遍历。
3. 动态数组初始化
上面的例子中,Dynamic_Arr2并未进行初始化,若想进行默认初始化,需要在数组后面加上一个小括号。
int* Dynamic_Arr3 = new int[size](); //默认的初始化;
此时数组中的十个值都为0;
也可以利用花括弧进行显式的初始化,例子如下;
string* Dynamic_Arr4 = new string[size]{"aa", "bb","cc", "dd", string(2, 'e') }; //显式的初始化
注意:显式地初始化时,元素数目不能大于数组大小。其次,显式初始化可能会因为编译器版本原因报错,笔者在VS2013与VS2017下进行测试,VS2013下在释放内存时出现内存错误。
4. 动态数组释放
释放动态数组时,使用delete[ ] arr_name;即在数组名前加上一个中括弧;例如
delete [ ] Dynamic_Arr4;
释放一个动态数组时,或者说是指向数组的指针时,空括号是必须的。它告诉编译器,指针指向一个数组的第一个元素。
delete释放数组是逆序进行的,最后一个元素被最先释放,第一个元素最后一个被释放。
使用动态数组时,一定要记得显式的释放内存,否则很容易出错,比如在一个大的工程中,某一个for循环中或者某个函数中申请了内存却没释放,当函数不断地被调用,这些申请过的内存会一直堆积,直到最后退出程序。这很可能造成非常大的麻烦。
比如下面两个函数;
void not_delete_fun()
{
int *arr_test = new int[10];
cout << arr_test << endl;
//delete[] arr_test;
}
void delete_fun()
{
int *arr_test = new int[10];
cout << arr_test << endl;
delete[] arr_test;
}
分别调用和释放两个函数三次,看看结果;
可以看出,释放过内存后,每次数组申请的内存是一致的,未释放内存的函数,每次申请数组的内存是不一样的,说明这些数组申请的内存并不会自动释放,而是会随着程序运行一致累积。
4. 多维动态数组的内存申请
//-----------------多维数组内存申请-------------------//
int MAX_NUM = 10;
int COL_NUM = 5, ROW_NUM = 3;
double ***Arr3D = new double **[MAX_NUM];
for (int i = 0; i < MAX_NUM; i++)
{
Arr3D[i] = new double *[ROW_NUM];
for (int j = 0; j < ROW_NUM; j++)
{
Arr3D[i][j] = new double[COL_NUM];
}
}
从上面可以看出,多维数组的申请与多维vector的定义类似,是一层一层的申请内存的,返回的是指向指针数组的指针。
先依次声明维度的大小,然后从最低维度开始申请内存。先申请ROW_NUM个大小为COL_NUM的数组,将指向这些数组的首地址的指针传递到大小为ROW_NUM的数组中,构成一个新的数组,以此类推,完成内存申请。
上面的例子中得到的是一个10层,3行,5列的数组。
5. 多维动态数组内存释放
多维动态数组的释放是从最低维度开始的。先释放掉最低维度的一维数组,然后依次释放内存,直到释放掉最高维度。就跟一层一层的拆房子一样。
for (int i = 0; i < MAX_NUM; i++)
{
for (int j = 0; j < ROW_NUM; j++)
{
delete[] Arr3D[i][j];
}
delete[] Arr3D[i];
}
delete[] Arr3D;
6. 最后
C++中还提供了allocator类进行动态数组的内存申请,大家可以根据需要自己学习。在此不做讲解。最后附上所有代码,需要的小伙伴可以自行使用。
#include <iostream>
#include <string>
using namespace std;
void not_delete_fun()
{
int *arr_test = new int[10];
cout << arr_test << endl;
//delete[] arr_test;
}
void delete_fun()
{
int *arr_test = new int[10];
cout << arr_test << endl;
delete[] arr_test;
}
int main()
{
int *Dynamic_Arr1 = NULL;
Dynamic_Arr1 = new int[10];
int size = 10;
int *Dynamic_Arr2 = new int[size]; //未初始化;
int *Dynamic_Arr3 = new int[size]{10,9,2,8,3,6,4}; //默认的初始化;
string a = "ee";
string *Dynamic_Arr4 = new string[size]{"aa", "bb", "cc", "dd", string(1, 'e'), "aa", "bb", "cc", "dd", string(2, 'e')}; //显式的初始化
//string *Dynamic_Arr4 = new string[size];
//cout << Dynamic_Arr4[4] << endl;
cout << "未释放内存的数组位置" << endl;
for (int i = 0; i < 3; i++)
{
not_delete_fun();
}
cout << "释放过内存的数组位置" << endl;
for (int i = 0; i < 3; i++)
{
delete_fun();
}
//-----------------多维数组内存申请-------------------//
int MAX_NUM = 10;
int COL_NUM = 5, ROW_NUM = 3;
double ***Arr3D = new double **[MAX_NUM];
for (int i = 0; i < MAX_NUM; i++)
{
Arr3D[i] = new double *[ROW_NUM];
for (int j = 0; j < ROW_NUM; j++)
{
Arr3D[i][j] = new double[COL_NUM];
}
}
//cout << Arr3D[9][4][2] << endl;
for (int i = 0; i < MAX_NUM; i++)
{
for (int j = 0; j < ROW_NUM; j++)
{
delete[] Arr3D[i][j];
}
delete[] Arr3D[i];
}
delete[] Arr3D;
delete[] Dynamic_Arr1;
delete[] Dynamic_Arr2;
delete[] Dynamic_Arr3;
delete[] Dynamic_Arr4;
system("pause");
return 0;
}
相关文章 细说C++中的数组之静态数组