C++基础:基于循环和将C样式数组传递给函数的范围

C++ basics: ranged based for-loop and passing C-style arrays to functions

本文关键字:数组 样式 范围 函数 基础 于循环 循环 C++      更新时间:2023-10-16

我正在努力学习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中一样?因此,这个函数中基于ranged的for循环将不会编译,因为我们没有数组的大小数据,对吧?

最后,当我们尝试在主循环中使用基于ranged的for循环进行打印时,我们到底向循环传递了什么?它是指向数组中第一个元素的指针吗?如果是,如果printArray2中的for循环不接受指针,为什么要编译它?

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

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

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

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

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

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

[3]的情况下,函数从其类型中知道数组的大小。引用通常被实现为指向所引用事物的指针,但在C++中,为了留下实现细节(有时可以进行优化),需要花费很大的篇幅。引用是其他地方数据的别名,与指针(类似于邮政地址)略有不同。当编译器有长度,并且C++做正确的事情时,迭代很容易。

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

根据关于数组和基于Ranged的循环的cppreference

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

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

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

示例:

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

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