3

我正在尝试学习 C++,但我无法在这里围绕这段代码,尽管花了很多时间寻找答案:

#include <iostream>

void printArray1(int (&array)[3]) {
    for(int x : array)
        std::cout << x << " ";
}

void printArray2(int array[]) { 
    for(int x : array) // compiler error, can't find begin and end
        std::cout << x << " ";
}

int main() {
    int a[3] = {34,12,88};

    for(int x : a)
        std::cout << x << " ";
    std::cout << std::endl;

    printArray1(a);
    printArray2(a);
    std::cout << std::endl;

    return 0;
}

在 printArray1 中,我们接收到一个对大小为 3 的数组的引用的参数。这是否意味着我们正在接收整个数组的地址,或者我们只是接收到大小为 3 的数组中第一个元素的地址?另外,这个参数是如何传递给循环的?

在 printArray2 中,我们接收到指向数组中第一个元素的指针,对吗?换句话说,我们也收到了一个地址,就像在 printArray1 中一样?因此,此函数中基于范围的 for 循环将无法编译,因为我们没有数组的大小数据,对吧?

最后,当我们尝试在 main 中使用基于范围的 for 循环进行打印时,我们传递给循环的究竟是什么?它是指向数组中第一个元素的指针吗,如果是,如果 printArray2 中的 for 循环不接受指针,为什么它会编译?

我对 C++ 的理解还很初级,所以非常感谢您的帮助,谢谢!

4

3 回答 3

6

基于范围的 for 循环适用于所有可以与std::begin和一起使用的类型std::end

数组和指针不一样。数组有固定的大小,指针没有。因此std::begin并且std::end适用于数组 - 但不适用于指针。这也解释了为什么基于范围的 for 循环适用于其中一个,而不适用于另一个。

数组也可能衰减为指针。例如,当传递给带有指针参数的函数时,就会发生这种情况。或者,当传递给采用不确定大小的数组参数(实际上与指针参数相同)的函数时。发生这种情况时,尺寸信息会再次丢失。

所以这取决于你如何定义函数。第一个函数接受一个数组,第二个函数接受一个指针。这就是为什么第一个保留大小信息并且循环起作用的原因。

但是,它限制了该功能可以采取的措施。第二个函数可以使用int b[2],而第一个函数不能。

于 2016-05-01T23:26:19.217 回答
0

根据 cppreference 关于数组基于范围的 for 循环

printArray1中,数组参数是一个int 引用数组,每个引用将引用作为参数传递的数组的前 3 个值。

printArray2中,数组参数是一个指针,它指向作为参数传递的数组的第一个值。有了它,您可以访问数组的所有值。

最后,它不是指针,而只是a数组的引用。在这种特殊情况下,重要的是要知道对于每次迭代,迭代值的副本将被执行到x变量。如果你想防止所有这些副本发生,你应该声明一个引用。

例子:

for(int &x : a)
    std::cout << x << " ";

顺便说一句,您还应该看看数组容器,它是现代风格的数组。

于 2016-05-01T23:42:11.087 回答
0

在这种[3]情况下,函数从其类型中知道数组有多大。引用通常被实现为指向被引用事物的指针,但在 C++ 中,为了留下实现细节(有时会启用优化),会花费大量时间。引用是别处数据的别名,与指针(类似于邮政地址)略有不同。当编译器有足够的长度时,迭代很容易,而且 C++ 做的事情是正确的。

在这种[]情况下,这是 C 风格的语法。它不是参考。和 的意思一样int * array。数组的大小既不是 tue 编译时类型(在函数内)的一部分,也不是运行时状态(它是单个 int 指针)的一部分。显然,如果没有长度,迭代是不可能的。

于 2016-05-01T23:21:38.497 回答