前言

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

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

#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. pycharm远程SSH调用服务器python解释器教程

    该教程主要介绍pycharm远程SSH调用解释器以及建立SFTP文件传输协议: 第一步:建立SSH连接: 第二步:建立SFTP协议: (1)SSH: 配置远程python解释器 这里主要讲的是如何配置 ...

  2. 保存wave音频流的方法

    保存到文件: void saveToFile(String filename, ByteBuffer buffer) { byte[] bytes = buffer.array(); OutputSt ...

  3. 比较两个数组的键名,并返回交集:array_intersect_key

    $a1=array("a"=>"red","b"=>"green","c"=>&q ...

  4. 修改ecshop的70种技巧

    1.如何修改网站”欢迎惠临本店”答复(dafu):languages\zh_cn\common.php文件中,$_LANG['welcome']=’欢迎惠临本店’:将他修改成你需要的字样. 2.如何修 ...

  5. 虚拟机VMWare的操作

    软件测试工程师需要搭建测试环境——虚拟机操作. VMWare Workstation虚拟机:模拟真实的环境进行各种试验和操作,启动之后,会占用一部分的系统资源. 官网安装:http://www.vmw ...

  6. Java多线程概念及优缺点,多线程的地位|乐字节

    大家好,乐字节小乐有来咯,上次说完了Java网络编程探究|乐字节,这次我们来看看线程相关的吧. Java线程主要讲述的内容有: 1.线程概念 多线程,说白了就是多条执行路径,原来是一条路径,就主路径( ...

  7. LeetCode 459. 重复的子字符串(Repeated Substring Pattern)

    459. 重复的子字符串 459. Repeated Substring Pattern 题目描述 给定一个非空的字符串,判断它是否可以由它的一个子串重复多次构成.给定的字符串只含有小写英文字母,并且 ...

  8. LeetCode 515. 在每个树行中找最大值(Find Largest Value in Each Tree Row)

    515. 在每个树行中找最大值 515. Find Largest Value in Each Tree Row 题目描述 You need to find the largest value in ...

  9. [SQL SERVER] - 还原数据库备份(SQL脚本),抛出 "System.OutOfMemoryException" 异常之解决

    背景 在 Microsoft SQL Server 2016 的查询窗体中,直接还原备份数据库的 SQL 脚本(99MB),抛出 Cannot execute script 异常: 原因 相关资料说: ...

  10. todo---git 生成密钥 原理分析

    ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDRJkDZ2z7syFC2QDCaORKF41ecwbL/kyFwkycOVE3MavTRBliAhoAhOaZQTr4j ...