blueyi's notes

Follow Excellence,Success will chase you!

0%

C/C++中二维动态数组的使用方法举例

C/C++中的二维数组实际上都是以一维数组为元素的一维数组,C++中可以有三种方式申请动态数组:

  • 使用C语言中的malloc分配,free释放
  • 使用C++中的new[]分配,delete[]释放
  • 使用C++中的vector实现

下面分别举例说明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/*
* dynamic_2dimension_arr.cpp
* Copyright (C) 2016 <@BLUEYI-A0835>
*
* Distributed under terms of the MIT license.
*/

#include <iostream>
#include <vector>

//声明一个m * n的动态二维数组,使用函数返回该二维数组,并分别使用malloc和new分配空间
//谨记二给数组即是数组的数组

//这三个函数用于验证二维数组的使用
//初始化一个二维数组
void iniarr(int** arr, int m, int n)
{
for (int i = 0; i < m; ++i)
for (int j = 0; j < n; ++j)
arr[i][j] = i + j;
}

//输出一个二维数组中的值
void printarr(int** arr, int m, int n)
{
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
std::cout << arr[i][j] << " ";
}
std::cout << std::endl;
}
std::cout << std::endl;
}

//调用上面两个函数,表示使用二维数组arr
void usearr(int** arr, int m, int n)
{
iniarr(arr, m, n);
printarr(arr, m, n);
}


//使用malloc定义二维数组,两步分配空间,分配的各维空间可能不连续
int** mularr_ma(int m, int n)
{
//声明一个含有m个元素的一维数组,每个数组中的元素都是int*类型(即另一个一维数组)
//并分配空间,相当于二维的m行
int **arr = (int**)malloc(m * sizeof(int*));
for (int i = 0; i < m; ++i)
arr[i] = (int*)malloc(n * sizeof(int)); //为一维数组中的每个指针元素申请n个int大小的空间,相当于二维中的列
return arr;
}


//使用malloc一步分配所有第二维的空间,分配的各维空间连续
int** mularr_ma2(int m, int n)
{
//声明一个含有m个元素的一维数组,每个数组中的元素都是int*类型(即另一个一维数组)
//并分配空间,相当于二维的m行
int **arr = (int**)malloc(m * sizeof(int*));
arr[0] = (int*)malloc(m * n * sizeof(int)); //注意arr[0]的内存很大,直接就是m*n个int的空间
for (int i = 1; i < m; ++i) //让arr[1]到arr[m-1]分别指向arr[0]后面的空间
arr[i] = arr[i-1] + n; //每次跳过0个元素
return arr;
}

//使用new分两步分配,各列所处内存可能不连续
int** mularr_new(int m, int n)
{
int **arr = new int*[m]; //m行
for (int i = 0; i < m; ++i)
arr[i] = new int[n]; //每行n列
return arr;
}

//使用new分配各列连续的内存,类似上面
int** mularr_new2(int m, int n)
{
int **arr = new int*[m]; //m行
arr[0] = new int[m * n];
for (int i = 1; i < m; ++i)
arr[i] = arr[i - 1] + n;
return arr;
}

//使用vector代替二维数组
//其实就是vector的vector
std::vector<std::vector<int>> mulvec(int m, int n)
{
//声明一个含有m个元素的vector,每个vector使用含有n个int的vector填充
std::vector<std::vector<int>> res(m, std::vector<int>(n));
return res;
}

//使用vector,为了效率,传递引用
void usevec(std::vector<std::vector<int>> &vec)
{
//可以像二维数组一样使用
//赋值
for (int i = 0; i < vec.size(); ++i)
for (int j = 0; j < (vec[0]).size(); ++j)
vec[i][j] = i + j;

//遍历输出
for (auto i : vec) {
for (auto j : i)
std::cout << j << " ";
std::cout << std::endl;
}
std::cout << std::endl;
}


int main(void)
{
int m = 5, n = 6;
int **arr = mularr_ma(m, n);
usearr(arr, m, n);
//malloc需要使用free释放,释放时先释放每一行,再释放外层一维数组
for (int i = 0; i < m; ++i)
free(arr[i]);
free(arr);

arr = mularr_ma2(m, n);
usearr(arr, m, n);
//注意此处释放只需要先释放arr[0],再释放arr即可,不能现你上面那样释放,不然就会重复释放
free(arr[0]);
free(arr);

arr = mularr_new(m, n);
usearr(arr, m, n);
//new的数组需要使用delete[]释放
for (int i = 0; i < m; ++i) //先释放各维中的内存
delete[] arr[i];
delete[] arr; //再释放最外层这一维的内存

arr = mularr_new2(m, n);
usearr(arr, m, n);
//先释放arr[0],再释放arr即可
delete[] arr[0];
delete[] arr; //再释放最外层这一维的内存

//使用vector代替二维数组
std::vector<std::vector<int>> varr = mulvec(m, n);
usevec(varr);
//容器不需要手动管理内存,非常棒
return 0;
}

对于已经确定一维的情况
1.假如已知第一维为5,第二维为变量n,声明二维数组

1
2
3
4
5
6
7
8
int *a[5];  //定义一个含有5个变量的一维数组,每一个元素含有一个int*的元素
//然后为每一维分配第二维的空间
for (int i = 0; i < 5; ++i)
a[i] = new int[n];
usearr(a, 5, n);
//只需释放手动分配的即可
for (int i = 0; i < 5; ++i)
delete[] a[i];

2.假如已知第二维为6,第一维为变量m,声明二维数组

1
2
3
4
5
int (*b)[6];  //声明一个指针,该指针指向数组,数组中的元素为含有6个int元素的数组
b = new int[m][6]; //使用new开辟一个二维数组空间,注意这种情况下第二维必须已知
usearr(b, 5, n);//当然此处使用usearr()调用肯定不行,会报类型不匹配,因为usearr的第一个参数是int**
//只需释放手动分配的即可
delete[] b;

Welcome to my other publishing channels