【问题标题】:C++ basics: ranged based for-loop and passing C-style arrays to functionsC++ 基础:基于范围的 for 循环和将 C 风格的数组传递给函数
【发布时间】:2016-08-26 15:55:37
【问题描述】:

我正在尝试学习 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++的理解还是比较初级的,非常感谢大家的帮助,谢谢!

【问题讨论】:

  • 您自己通过调试程序看到了吗?它打印什么?

标签: c++ arrays parameter-passing ranged-loops


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

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

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

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

    但是,它限制了函数可以使用的内容。第二个函数可以使用int b[2],而第一个函数不能。

    【讨论】:

    • 所以基本上,当我在 main() 中使用标识符 a 时,我将数组类型传递给循环,对吗?但是 a 仍然是数组中第一个元素的地址,就像一个指针,只是它有一个固定的大小,如你所说?
    • 不完全是,a 绝不是“数组中第一个元素的地址”。 a 数组,具有固定大小。您甚至不应该将数组和指针视为相同的类型,数组与地址无关,唯一的关系是数组可以在赋值时衰减为指针(无论是将其分配给变量还是将其作为函数参数传递)。查看数组衰减以了解更多信息。
    • 啊,好吧,当我们将 a 传递给基于范围的循环时,说数组没有衰减是否有效,并且没有衰减为我们将 a 传递给第一个函数,其中参数是引用,是吗?
    • 正确。衰减只发生在调用后一个函数时,因为数组可以隐式转换为指针。这就是尺寸信息丢失的地方。
    • 完美,非常感谢!
    【解决方案3】:

    根据 cppreference 关于arraysRanged-based for loop

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

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

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

    例子:

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

    顺便说一句,您还应该看看array container,这是现代风格的数组。

    【讨论】:

      猜你喜欢
      • 2014-12-04
      • 1970-01-01
      • 1970-01-01
      • 2013-01-04
      • 1970-01-01
      • 2021-01-21
      • 2015-10-27
      • 2021-04-08
      相关资源
      最近更新 更多