【C++】细说C++中的数组之动态数组

 

fishing-panhttps://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++中的数组之静态数组
 


版权声明:本文为u013921430原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
THE END
< <上一篇
下一篇>>