在c++中使用二级指针
在c++中使用二级指针
问题
在程序中,二维数组是我们描述问题的得力助手,比如2048游戏中的网格,国际象棋中的棋盘等。
可是大多数时候静态的二维数组并不能满足所有的情况,试想我要创建一个m*n
的矩阵,可是m
和n
的值要通过用户的输入才能知道,如果我们像下面这样来构建我们的程序(a.cpp):
#include <iostream>
using namespace std;
int main() {
int m, n;
cin >> m;
cin >> n;
int array[m][n];
return 0;
}
接着我们编译:
g++ a.cpp -o a
按理说程序应该会报错,可是为什么编译成功了??听听StackOverflow上的大佬怎么说的:
[tips]
c++并不支持VLA(Variable Length Array)也就是,变长数组!显然gcc/g++的作者并不这么想!他们热爱这种兼容性!
如果我们用vc来编译这段代码,显然是不能通过编译的!为什么如此呢?因为局部变量是存在栈中的,显然上面那一段代码中array
变量会被分配到栈中,可是在编译过程中,程序并不知道应该给array
分配多少内存空间,所以自然无法编译通过。
方法
我们自然想到了二级指针,顾名思义,二级指针就是指针的指针,如果p
是一个二级指针,那么*p
就是一个一级指针,**p
则是指针的内容。通过二级指针就可以方便的描述二维数组。
#include <iostream>
using namespace std;
int main() {
int i, j;
int **b;
// 开辟行
b = new int *[8];
// 开辟列
for (i = 0; i < 8; ++i)
*(b + i) = new int[8];
for (i = 0; i < 8; ++i) {
for (j = 0; j < 8; ++j)
b[i][j] = 7;
}
return 0;
}
代码中b
是一个二级指针,b = new int *[8];
相当于开辟了二维数组的行随后的循环相当于开辟了二维数组的列。在内存中b
是一个指针他指向了8 × 4个字节的连续内存区域,每四个字节中又存放了一个指针,每个指针又指向了8 × 4个字节的连续内存区域,每四个字节中存放了一个整型变量。下面的图很好的描述了内存情况,图中每个方格代表四个字节。
+-----------+ +-----------+
0x1281954:| 0x1287650 | 0x1287650:| 7 |
+-----------+ +-----------+
0x1281950:| 0x1287618 | 0x1287618:| 7 |
+-----------+ +-----------+
0x128194c:| 0x12875e0 | 0x12875e0:| 7 |
+-----------+ +-----------+
0x1281948:| 0x12875a8 | 0x12875a8:| 7 |
+-----------+ +-----------+
0x1281944:| 0x1287570 | 0x1287570:| 7 |
+-----------+ +-----------+
0x1281940:| 0x1287538 | 0x1287538:| 7 |
+-----------+ +-----------+
0x128193c:| 0x1287500 | 0x1287500:| 7 |
+-----------+ +-----------+ +-----------+
b: | 0x1281938 | +--> 0x1281938:| 0x12874c8 | +--> 0x12874c8:| 7 |
+-----------+ +-----------+ +-----------+
*(b+i) *(*(b+i)+j)
并且动态分配的空间会被保存在堆里,这意味着你有更大的灵活性来选择什么时候来申请这些空间,什么时候选择删除这些空间。