在c++中使用二级指针

Tue Apr 23 2019 on C++ 学习

在c++中使用二级指针

问题

在程序中,二维数组是我们描述问题的得力助手,比如2048游戏中的网格,国际象棋中的棋盘等。

可是大多数时候静态的二维数组并不能满足所有的情况,试想我要创建一个m*n的矩阵,可是mn的值要通过用户的输入才能知道,如果我们像下面这样来构建我们的程序(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)

并且动态分配的空间会被保存在堆里,这意味着你有更大的灵活性来选择什么时候来申请这些空间,什么时候选择删除这些空间。

Related

Comments

comments powered by Disqus