C++——多维数组动态开辟与释放
前言
在讨论多维数组动态开辟与释放之前,先说说什么是二维数组静态开辟与释放。
形如这种就是静态开辟内存,事先画好了内存大小
#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++——多维数组动态开辟与释放的更多相关文章
- C Program进阶-二维数组动态内存开辟
对于二维数组,我们知道可以用Type ArrayName[Row][Colume]的方式来定义,这是一种静态内存开辟的方式,程序在编译的时候就为该数组分配了空间,而且行和列大小也是指定的.这篇文章里我 ...
- C++二维数组动态申请内存
好久没用C++刷题了,今天早上刷了几条题,感觉很陌生了.怪我,大二下实在太颓废了,没啥作为. 今天更新个关于c++二维数组内存申请的问题,当初作为菜鸟初学指针的时候,还是在这方面有点搞不通的.今天用到 ...
- C++基础:二维数组动态的申请内存和释放内存
使用二维数组的时候,有时候事先并不知道数组的大小,因此就需要动态的申请内存.常见的申请内存的方法有两种:malloc/free 和 new/delete. 一.malloc/free (1)申请一维数 ...
- 2017.11.17 C++系列---用malloc动态给c++二维数组的申请与释放操作
方法一:利用二级指针申请一个二维数组. #include<stdio.h> #include<stdlib.h> int main() { int **a; //用二级指针动态 ...
- C++二维数组动态内存分配
对于二维数组和二维指针的内存的分配 这里首选说一下一维指针和一维数组的内存分配情况. 一维: 数组:形如int a[5];这里定义了一个一维数组a,并且数组的元素个数是5,这里的a是这五个元素的整体 ...
- c指针与数组,传参问题,指针数组与数组指针的区别,二维数组动态内存分配
一 数组的结构:顺序存储,看谭浩强中的图,牢记 1.数组名指代一种数据结构:数组 现在可以解释为什么第1个程序第6行的输出为10的问题,根据结论1,数组名str的内涵为一种数据结构,即一个长度为10的 ...
- C++ 动态多维数组的申请与释放
今天在实验室的项目中遇到了一个问题,直接上代码: void ViBe::init(Mat img) { imgcol = img.cols; imgrow = img.rows; // 动态分配三维数 ...
- JavaScript中给二维数组动态添加元素的质朴方法
var myData = new Array(); for(var i=0;i<tableDatas.length;i++){ var arr=tableDatas[i]; ...... /// ...
- C++中动态申请二维数组并释放方法
C/C++中动态开辟一维.二维数组是非常常用的,以前没记住,做题时怎么也想不起来,现在好好整理一下. C++中有三种方法来动态申请多维数组 (1)C中的malloc/free (2)C++中的new/ ...
随机推荐
- vmware安装gho系统(win10上安装虚拟机然后在vmware上安装win7)
用ghost直接将gho转成vmdk将ghost32, gho文件放到同一目录, cmd里进入对应目录,输入以下命令ghost32 -clone,mode=restore,src=example.gh ...
- win10安装MySQL 8
下载并解压MySQL Server(官方有MySQL Installer 8.0.13,但是我安装没有成功) 将MySQL Server的bin目录加入到系统变量Path中. 找一个my.ini文件放 ...
- DevOps - DevOps精要 - 落地
1 - 关键问题 如何向不具备相关基础知识的人说明和解释DevOps? 如何在组织和团队中推广和实施DevOps? 2 - 在组织中实施DevOps 在全新的组织或服务开发中,没有既定规则和老旧的习惯 ...
- 上传大文件到腾讯云cos遇到的一些问题
讲一个开发遇到的问题. 开发中遇到一个需求,需要在后台表单页面支持上传视频.因为项目中一直用的是腾讯云的COS做第三方存储平台,所以视频也要上传到cos中保存.首先想到的是使用腾讯提供的php的SDK ...
- 使用wkwebview时,push后,再pop返回,报错
使用wkwebview时,push后,再pop返回,报错 Cannot form weak reference to instance (xxxx) of class xxxx. It is poss ...
- gensim中word2vec
from gensim.models import Word2Vec Word2Vec(self, sentences=None, size=100, alpha=0.025, window=5, m ...
- 【转】MySQL中EXISTS的用法
原文链接:https://www.cnblogs.com/qlqwjy/p/8598091.html 比如在Northwind数据库中有一个查询为 SELECT c.CustomerId,Compan ...
- 【dfs】Sequence Decoding
Sequence Decoding 题目描述 The amino acids in proteins are classified into two types of elements, hydrop ...
- NodeJS入门--环境搭建 IntelliJ IDEA
NodeJS入门–环境搭建 IntelliJ IDEA 本人也刚开始学习NodeJS,所以以此做个笔记,欢迎大家提出意见. 1.首先 下载安装NodeJS,下载安装IntelliJ IDEA 2.接下 ...
- git 修改注释
原文:https://www.jianshu.com/p/098d85a58bf1 修改最后一条注释: git commit --amend 如果已经推送到远程,强制push到远程仓库: git pu ...