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

【C++】细说C++中的数组之动态数组nbsp fishing pan https blog csdn net u0 转载请注明出处 1 前言 nbsp nbsp nbsp 上周 写了一篇 细说 C 中的数组之静态数组 今天讲述一下动态数组 nbsp nbsp 数组是一种顺序存储的数据结构 在定义数组时 首先要确定数组的大小 静态数组在编译时就需要确定数组的大小 所以 为了防止内存溢出 我们尽量将数组定义的大一些 但是这样太过浪费内存

 

fishing-pan:https://blog.csdn.net/u0转载请注明出处】

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; }

     分别调用和释放两个函数三次,看看结果;

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

      可以看出,释放过内存后,每次数组申请的内存是一致的,未释放内存的函数,每次申请数组的内存是不一样的,说明这些数组申请的内存并不会自动释放,而是会随着程序运行一致累积。

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 
  
    #include 
   
     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; } 
    
  
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/207796.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月19日 下午1:05
下一篇 2026年3月19日 下午1:05


相关推荐

  • linux中八进制数对应符号,八进制

    linux中八进制数对应符号,八进制JavaScript 三 JS 进制转换 2021 05 1509 32 27 十进制转二进制模二取余十进制转八进制模八取余十进制转 16 进制模 16 取余所以 52 的二进制十进制转二进制 再将二进制转八进制和十六进制二进制转八进制 规则 从右往左数 每三位一组 不足三位用 0 补齐 最后将每一组数转成八进制进制二进制转八进制转八进制 Octal 八进制 Octal

    2026年3月17日
    1
  • office word 公式编号

    office word 公式编号方式 1 推荐 word2016 在公式的最后键入 和标号 然后回车就有了标号方式 2 画表格 1 插入三栏表格 2 将公式放入中列表格中居中对齐 将编号放入右列表格中靠右对齐 3 将表格边距设为 0 最后隐去表格外框方式 3 制表符 作者 知乎用户链接 https www zhihu com question answer 效果 公式在行的最中间 序号在行的最右边 且序号在垂直位置也与公式对齐 公式的插入就不说了 直接插入 gt 公式 然后输

    2026年3月16日
    2
  • R语言-提取字符长度nchar函数与length函数「建议收藏」

    R语言-提取字符长度nchar函数与length函数「建议收藏」R语言中nchar函数:主要使用来返回字符长度而length函数:则是用来返回字符数量#Gettingthelengthofastringx=”John”y=c(“Jim”,”Tony”,”kavry”)nchar(x)#returnthenumberofcharactersinthestringnchar(y)#ifavector,return

    2022年5月29日
    41
  • PyCharm跳回上一步操作和撤销操作

    PyCharm跳回上一步操作和撤销操作pycharm 是 Python 的开发工具 我们经常会用 alt b 进入某个方法查看具体实现或者用法 Demo 如果 tab 开的不多 我们可以通过 tab 标签找到原始页面 但是标签太多 我们不好管理 因此可以通过快捷方式 ctrl alt 左箭头 退回到原始页面 也可以在 pycharm 的顶层选项 View 中 把跳回箭头显示出来 把 View 中的 Toolb

    2026年3月27日
    1
  • android.app.Fragment$InstantiationException的原因分析

    android.app.Fragment$InstantiationException的原因分析每个Fragment必须要有一个无参构造方法,这样该Fragment在Activity恢复状态的时候才可以被实例化。强烈建议,Fragment的子类不要有其他含参构造方法,因为这些构造方法在Fragment重新实例化时不会被调用。取而代之的方式是,通过setArguments(Bundle)设置参数,然后通过getArguments获得参数。

    2022年7月16日
    19
  • Do we need other languages other than C and C++?

    Do we need other languages other than C and C++?

    2021年12月3日
    53

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号