C++多维数组如何在幕后工作

C++ How multi-dimensional arrays works behind the scenes

本文关键字:工作 数组 C++      更新时间:2023-10-16

我是C++的新手,正在努力理解一件重要的事情。我听说所有数组都只是指针别名,[]运算符执行的每个操作都转换为指针解引用。请参见下面的示例(动态数组)。

auto **tab = new int*[2];
tab[0] = new int[2];
tab[1] = new int[2];
tab[0][0] = 1;
tab[0][1] = 2;
tab[1][0] = 3;
tab[1][1] = 4;
cout << "tab[0] address: " << &tab[0] << " with value: " << tab[0] << endl;
cout << "tab[1] address: " << &tab[1] << " with value: " << tab[1] << endl;
cout << "tab[0][0] address: " << &tab[0][0] << " with value: " << tab[0][0] << endl;
cout << "tab[0][1] address: " << &tab[0][1] << " with value: " << tab[0][1] << endl;
cout << "tab[1][0] address: " << &tab[1][0] << " with value: " << tab[1][0] << endl;
cout << "tab[1][1] address: " << &tab[1][1] << " with value: " << tab[1][1] << endl;
delete[] tab[0];
delete[] tab[1];
delete[] tab;

这是一个非常简单的程序,它展示了如何在内存中表示指针对指针。它返回以下结果:

tab[0] address: 0x7114d0 with value: 0x7114e0
tab[1] address: 0x7114d4 with value: 0x7114f0
tab[0][0] address: 0x7114e0 with value: 1
tab[0][1] address: 0x7114e4 with value: 2
tab[1][0] address: 0x7114f0 with value: 3
tab[1][1] address: 0x7114f4 with value: 4

注意:我完全理解它的工作原理。我有两个基本地址,它们指向其他第二个地址。结果,解引用tab[0]将存储器地址返回到第二维度。伪代码:

*(0x7114d0) = 0x7114e0 -> 1

但是第二个例子展示了静态数组是如何工作的。

int tab[2][2] = {{1,2}, {3,4}};
cout << "tab[0] address: " << &tab[0] << " with value: " << tab[0] << endl;
cout << "tab[1] address: " << &tab[1] << " with value: " << tab[1] << endl;
cout << "tab[0][0] address: " << &tab[0][0] << " with value: " << tab[0][0] << endl;
cout << "tab[0][1] address: " << &tab[0][1] << " with value: " << tab[0][1] << endl;
cout << "tab[1][0] address: " << &tab[1][0] << " with value: " << tab[1][0] << endl;
cout << "tab[1][1] address: " << &tab[1][1] << " with value: " << tab[1][1] << endl;

与前面的例子相同,我得到的结果是:

tab[0] address: 0x28fea0 with value: 0x28fea0
tab[1] address: 0x28fea8 with value: 0x28fea8
tab[0][0] address: 0x28fea0 with value: 1
tab[0][1] address: 0x28fea4 with value: 2
tab[1][0] address: 0x28fea8 with value: 3
tab[1][1] address: 0x28feac with value: 4

在这一点上,我遇到了一个巨大的问题,如何理解这一点,因为取消引用"tab[0]"会返回"tab[0]"的地址,该地址也包含值(1)。。。伪码

*(0x28fea0) = 0x28fea0 -> 1

现在你怎么理解它在内存中,静态和动态多维数组似乎有两种不同的处理方式。如果数组实际上是指针,那么通过tab[0]处理自己的地址(下面的伪代码),静态数组去引用是如何工作的。。。

2D数组和指针数组是不同的动物,即使它们的语法相同。

这是一个指向数组的指针数组:

auto **tab = new int*[2];
tab[0] = new int[2];
tab[1] = new int[2];

tab是一个指针数组,tab的每个元素都指向,但这些行是相互独立分配的,并且不一定是连续的。理论上,它们甚至可以有不同的大小,这在C字符串数组中很常见。

这是一个2D阵列:

int tab[2][2];

它是一个数组。这里要求行具有相同的大小并连续分配:&tab[0][2]要求与&tab[1][0]相同

但is完全独立于静态或动态分配。这是一个静态的指针数组:

int row1[2] = { 0, 1};
int row2[2] = { 2, 3};
int *tab[] = { row1, row2 }; // row1 and row2 decay to pointers to their first element;

这是一个动态分配的2D阵列:

typedef int iarr2[2];
iarr2* dyntab = new iarr2[2];