前言

在讨论多维数组动态开辟与释放之前,先说说什么是二维数组静态开辟与释放。

形如这种就是静态开辟内存,事先画好了内存大小

#include<iostream>
using namespace std; #define ROW 3
#define COL 4
int main()
{
int ar[COL][ROW] = { };
return ;
}

使用二级指针模拟二维数组

代码演示

#include<iostream>
#include<assert.h>
using namespace std; #define ROW 3
#define COL 4
int main()
{
int **p=(int**)malloc(sizeof(int*)*ROW);
assert(NULL != p);
for (int i=;i<ROW;++i)
{
p[i] = (int*)malloc(sizeof(int)*COL);
assert(NULL!=p[i]);
}
for (int i = ; i< ROW; ++i)
{
for (int j = ; j < COL; ++j)
{
p[i][j] = i + j;
}
}
for (int i = ; i< ROW; ++i)
{
for (int j = ; j < COL; ++j)
{
cout << p[i][j]<<" ";
}
cout << endl;
}
return ;
}

这段代码有个问题,内存泄漏。

泄露内存大小为4*3 + 4*4*3 = 60 Byte。我们知道,进程的用户空间内存中有一段内存是程序运行时需要的(堆、栈、共享内存区),栈内存由OS动态开辟回收,我们malloc的内存时是在堆中,需要我们手动释放,否则就会内存泄露。

free(p)这么释放内存可以吗?

不可以,这么仅仅是把3个int*释放了,后面int*指向的内存泄露。

正确释放内存,先释放int*指向的内存,在释放p指向的内存(即3个int*内存)

 #include<iostream>
#include<assert.h>
using namespace std; #define ROW 3
#define COL 4
int main()
{
int **p=(int**)malloc(sizeof(int*)*ROW);
assert(NULL != p);
for (int i=;i<ROW;++i)
{
p[i] = (int*)malloc(sizeof(int)*COL);
assert(NULL!=p[i]);
}
for (int i = ; i< ROW; ++i)
{
for (int j = ; j < COL; ++j)
{
p[i][j] = i + j;
}
}
for (int i = ; i< ROW; ++i)
{
for (int j = ; j < COL; ++j)
{
cout << p[i][j]<<" ";
}
cout << endl;
}
for (int i=;i<ROW;++i)
{
free(p[i]);
}
free(p);
return ;
}

代码封装一下,malloc版本

 #include<iostream>
#include<assert.h>
using namespace std;
#define Type int
#define ROW 3
#define COL 4 Type** _Malloc(int row,int col)
{
Type **p = (Type**)malloc(sizeof(Type*)*row);
assert(NULL != p);
for (int i = ; i<row; ++i)
{
p[i] = (Type*)malloc(sizeof(Type)*col);
assert(NULL != p[i]);
}
return p;
} void _Assign(Type **p, int row, int col)
{
for (int i = ; i< row; ++i)
{
for (int j = ; j < col; ++j)
{
p[i][j] = i + j;
}
}
} void _Print(Type **p, int row, int col)
{
for (int i = ; i< row; ++i)
{
for (int j = ; j < col; ++j)
{
cout << p[i][j] << " ";
}
cout << endl;
}
} void _Free(Type **p, int row)
{
for (int i = ; i<row; ++i)
{
free(p[i]);
}
free(p);
}
int main()
{
Type **p = _Malloc(ROW,COL);
_Assign(p,ROW,COL);
_Print(p, ROW, COL);
_Free(p, ROW);
return ;
}

new版本

 #include<iostream>
#include<assert.h>
using namespace std;
#define Type int
#define ROW 3
#define COL 4 Type** _New(int row,int col)
{
Type **p = new Type*[row];
assert(NULL != p); //C++一般不用断言,而是使用异常机制
for (int i = ; i<row; ++i)
{
p[i] = new Type[col];
assert(NULL != p[i]);
}
return p;
} void _Assign(Type **p, int row, int col)
{
for (int i = ; i< row; ++i)
{
for (int j = ; j < col; ++j)
{
p[i][j] = i + j;
}
}
} void _Print(Type **p, int row, int col)
{
for (int i = ; i< row; ++i)
{
for (int j = ; j < col; ++j)
{
cout << p[i][j] << " ";
}
cout << endl;
}
} void _Delete(Type **p, int row)
{
for (int i = ; i<row; ++i)
{
delete []p[i];
}
delete []p;
}
int main()
{
Type **p = _New(ROW,COL);
_Assign(p,ROW,COL);
_Print(p, ROW, COL);
_Delete(p, ROW);
return ;
}

C++的常用做法

在C++里面开辟二维数组,实际上没有上面那么麻烦。在看懂下面代码之前,需要向理解下面的思想。

数组的首元数是谁,指向数组首元素的指针真么写?

对于一维数组,如下图,首元素就是整型。整型数组首元素的地址就是int*。所以一维数组接收地址就是一个整型指针int*。

对于二维数组,必然涉及到行和列,他的首元素就不再是其中单独一行的某一个元数,而是整体一行,首元素的地址就是(一维数组的地址)int**。所以二位数组接收地址就是int**,也就是说需要使用int**指向首元素,因为首元素是一维数组,数组是int*类型。

二维数组代码演示

 #include<iostream>
#include<assert.h>
using namespace std;
#define Type int
#define ROW 3
#define COL 4 //定义数组指针类型
typedef Type(*Ar)[COL];
Ar _New()
{
Ar p= new Type[ROW][COL];
return p;
} void _Assign(Ar p, int row, int col)
{
for (int i = ; i< row; ++i)
{
for (int j = ; j < col; ++j)
{
p[i][j] = i + j;
}
}
} void _Print(Ar p, int row, int col)
{
for (int i = ; i< row; ++i)
{
for (int j = ; j < col; ++j)
{
cout << p[i][j] << " ";
}
cout << endl;
}
} void _Delete(Ar p)
{
delete []p;
}
int main()
{
Ar p = _New();
_Assign(p,ROW,COL);
_Print(p, ROW, COL);
_Delete(p);
return ;
}

三维数组代码演示

 #include<iostream>
#include<assert.h>
using namespace std;
#define Type int
#define ROW 3
#define COL 4
#define Z 5 //定义数组指针类型
typedef Type(*Ar)[ROW][COL];
Ar _New()
{
Ar p = new Type[Z][ROW][COL];
return p;
} void _Assign(Ar p, int row, int col, int z)
{
static int count = ;
for (int i = ; i < row; ++i)
{
for (int j = ; j < col; ++j)
{
for (int k = ; k < z; ++k)
{
p[i][j][k] = ++count;
cout.width();
cout.flags(ios::left);
cout << p[i][j][k] << " ";
}
cout << endl;
}
cout << endl;
}
} void _Print(Ar p, int row, int col, int z)
{
for (int k = ; k < z; ++k)
{
for (int i = ; i < row; ++i)
{
for (int j = ; j < col; ++j)
{
cout.width();
cout.flags(ios::left);
cout << p[i][j][k] << " ";
}
cout << endl;
}
cout << endl;
}
} void _Delete(Ar p)
{
delete[]p;
}
int main()
{
Ar p = _New();
_Assign(p, ROW, COL, Z);
_Print(p, ROW, COL, Z);
_Delete(p);
return ;
}

C++——多维数组动态开辟与释放的更多相关文章

  1. C Program进阶-二维数组动态内存开辟

    对于二维数组,我们知道可以用Type ArrayName[Row][Colume]的方式来定义,这是一种静态内存开辟的方式,程序在编译的时候就为该数组分配了空间,而且行和列大小也是指定的.这篇文章里我 ...

  2. C++二维数组动态申请内存

    好久没用C++刷题了,今天早上刷了几条题,感觉很陌生了.怪我,大二下实在太颓废了,没啥作为. 今天更新个关于c++二维数组内存申请的问题,当初作为菜鸟初学指针的时候,还是在这方面有点搞不通的.今天用到 ...

  3. C++基础:二维数组动态的申请内存和释放内存

    使用二维数组的时候,有时候事先并不知道数组的大小,因此就需要动态的申请内存.常见的申请内存的方法有两种:malloc/free 和 new/delete. 一.malloc/free (1)申请一维数 ...

  4. 2017.11.17 C++系列---用malloc动态给c++二维数组的申请与释放操作

    方法一:利用二级指针申请一个二维数组. #include<stdio.h> #include<stdlib.h> int main() { int **a; //用二级指针动态 ...

  5. C++二维数组动态内存分配

    对于二维数组和二维指针的内存的分配 这里首选说一下一维指针和一维数组的内存分配情况. 一维: 数组:形如int  a[5];这里定义了一个一维数组a,并且数组的元素个数是5,这里的a是这五个元素的整体 ...

  6. c指针与数组,传参问题,指针数组与数组指针的区别,二维数组动态内存分配

    一 数组的结构:顺序存储,看谭浩强中的图,牢记 1.数组名指代一种数据结构:数组 现在可以解释为什么第1个程序第6行的输出为10的问题,根据结论1,数组名str的内涵为一种数据结构,即一个长度为10的 ...

  7. C++ 动态多维数组的申请与释放

    今天在实验室的项目中遇到了一个问题,直接上代码: void ViBe::init(Mat img) { imgcol = img.cols; imgrow = img.rows; // 动态分配三维数 ...

  8. JavaScript中给二维数组动态添加元素的质朴方法

    var myData = new Array(); for(var i=0;i<tableDatas.length;i++){ var arr=tableDatas[i]; ...... /// ...

  9. C++中动态申请二维数组并释放方法

    C/C++中动态开辟一维.二维数组是非常常用的,以前没记住,做题时怎么也想不起来,现在好好整理一下. C++中有三种方法来动态申请多维数组 (1)C中的malloc/free (2)C++中的new/ ...

随机推荐

  1. (NSNumber **)value和(NSNumber * __autoreleasing *)value

    今天在看别人开源项目的时候看到这样的代码: 正文从这里开始~~~ 定义如下: /** 评论详情页基础设置 @param BaseSettingBlock 基础设置 */ - (void)setUpCo ...

  2. dockerfile里面的内容编写顺序,必须严格按照顺序编写,否则编译不成

    完整文档请参照https://www.cnblogs.com/effortsing/p/10480972.html 这里只介绍dockerfile里面的步骤顺序 cat>/home/jenkin ...

  3. 登录另一台linux主机并且执行相应的命令

    [root@bogon ~]# cat a.sh #!/bin/bash ssh root@192.168.0.98 'ls /root'

  4. jquery分页展示控件:kkpager

    kkpager v1.2 js分页展示控件,传入简单参数就能使用的分页效果控件 准备工作,引入js.css <script type="text/javascript" sr ...

  5. 看烦了VS2012的黑白调调了吗?换

    VS2012的默认深色主题的确让整个IDE看起来很有气场,而且深色的主题保护眼睛,还是蛮不错的.但是看久了也会烦啊.虽然说重要的不是IDE看起来怎么样,而是写出来的代码质量怎么样,但一个好的环境也是会 ...

  6. 原生Js页面滚动延迟加载图片

    原理和过程1.页面滚动加载事件2.获取元素在页面里的top值 根据滚动条的位置 判断何时显示图片3.获取元素集合 加载过的图片从集合里删除 效果预览:http://jsfiddle.net/dtdxr ...

  7. JavaScript:学习笔记(10)——XMLHttpRequest对象

    JavaScript:学习笔记(10)——XMLHttpRequest对象 XHR对象 使用XMLHttpRequest (XHR)对象可以与服务器交互.您可以从URL获取数据,而无需让整个的页面刷新 ...

  8. Office 2010 经验总结

    1. 如何设置蓝底白字? 答:点击菜单项上的"页面布局"→"页面颜色",就可以选择喜欢的页面颜色,字体颜色也会跟着发生改变. 补充:如果不喜欢相应的页面颜色中系 ...

  9. CF1227D Optimal Subsequences

    思路: 首先对于单个查询(k, p)来说,答案一定是a数组中的前k大数.如果第k大的数字有多个怎么办?取索引最小的若干个.所以我们只需对a数组按照值降序,索引升序排序即可. 多个查询怎么办?离线处理. ...

  10. Word 带圈字符 1~20 快捷键的输入的技巧

    1. 前言 如何在Word中输入带圈数字?为大家分享一种快速录入带圈字符的方法,就是使用快捷键. 2. 输入带圈字符 1.在Word中输入2465,然后使用快捷键「ALT + X」就能变成⑥:输入24 ...