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

时间:2017-11-03 09:55:46

标签: c++ arrays pointers multidimensional-array

我是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)... Pseudocode

*(0x28fea0) = 0x28fea0 -> 1

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

1 个答案:

答案 0 :(得分:1)

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]相同

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

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];