【问题标题】:C++ How multi-dimensional arrays works behind the scenesC++ 多维数组如何在幕后工作
【发布时间】:2018-04-16 00:20:35
【问题描述】:

我是 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]' 的地址,它也持有 value(1)... 伪代码

*(0x28fea0) = 0x28fea0 -> 1

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

【问题讨论】:

  • 1) “听说所有数组都只是指针别名” 你听错了。数组不是指针。 2)“现在你是怎么理解的?”考虑阅读good C++ book,这里应该详细解释多维数组的概念。
  • 如果您认为数组只是指针,请比较 sizeof(pointer) 和 sizeof(array)。如果数组只是一个指针,他怎么知道数据有多长? (我还没有答案)
  • 在您的第一个片段中,您有一个指针数组(指向数组)。在第二个中,您有一个数组数组(大小为 2)。 int[2] 类型不同于 int[] 类型(通常衰减为指针)。如果有帮助,多维数组不是 C++ 语言的一部分——它们是我们对数组数组(或指针数组)的解释。
  • “我是 C++ 的新手,正在努力理解一件重要的事情。” 你需要理解的真正重要的事情是你不应该写 newdelete你自己,因为该语言提供了一个标准库,其中包含多种类型的容器,以避免您不得不考虑所有这些。相反,您可以使用 stdlib 编写代码来做有用的事情,如果您找到原始 new/delete 的利基用例,那么您可以在有原因时担心它们。
  • @underscore_d:我同意你的观点,但作为一个来自 C 的老恐龙,指针和数组之间的区别,以及二维数组和指针数组之间的区别对我来说似乎很重要。

标签: c++ arrays pointers multidimensional-array


【解决方案1】:

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

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

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

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

这是一个二维数组:

int tab[2][2];

它是一个数组数组。这里要求行具有相同的大小并连续分配:&amp;tab[0][2] 必须与 &amp;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;

这是一个动态分配的二维数组:

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

【讨论】:

    猜你喜欢
    • 2011-11-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-23
    • 2011-04-15
    • 1970-01-01
    • 2011-08-29
    • 2010-12-28
    • 1970-01-01
    相关资源
    最近更新 更多