C++ 基础知识:基于范围的 for 循环和将 C 风格数组传递给函数
C++ basics: ranged based for-loop and passing C-style arrays to functions
我正在尝试学习 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++ 的了解还很初级,非常感谢您的帮助,谢谢!
在 [3]
的情况下,函数根据其类型知道数组有多大。引用通常被实现为指向被引用事物的指针,但在 C++ 中,经过大量篇幅来留下实现细节(有时可以实现优化)。引用是其他地方数据的别名,与指针(类似于邮政地址)略有不同。当编译器有长度时迭代很容易,C++ 做正确的事。
在 []
的情况下,这是 C 风格的语法。它不是参考。与int * array
的意思相同。数组的大小既不是编译时类型(在函数内)的一部分,也不是运行时状态(它是单个 int 指针)的一部分。显然没有长度就不可能进行迭代。
基于范围的 for 循环适用于可与 std::begin
和 std::end
一起使用的所有类型。
数组和指针不一样。数组有固定大小,指针没有。因此 std::begin
和 std::end
适用于数组 - 但不适用于指针。这也解释了为什么基于范围的 for 循环适用于一个,但不适用于另一个。
数组也可能退化为指针。例如,当传递给采用指针参数的函数时,就会发生这种情况。或者,当传递给采用不确定大小的数组参数(实际上与指针参数相同)的函数时。发生这种情况时,尺寸信息将再次丢失。
所以这取决于你如何定义函数。第一个函数接受一个数组,第二个函数接受一个指针。这就是为什么第一个保留大小信息并且循环有效的原因。
但是,它限制了函数可以接受的内容。第二个函数可以接受 int b[2]
,而第一个不能。
根据cppreference约arrays and Ranged-based for loop
在 printArray1 中,array 参数是一个 int 引用 的数组,每个一个引用作为参数传递的数组的前 3 个值。
在 printArray2 中,array 参数是一个指针,指向作为参数传递的数组的第一个值。使用它,您可以访问数组的所有值。
最后,它不是指针,只是对 a 数组的引用。
在这种特殊情况下,重要的是要知道对于每次迭代,将对 x 变量执行迭代值的副本。
如果你想防止所有这些复制发生,你应该改为声明一个引用。
示例:
for(int &x : a)
std::cout << x << " ";
顺便说一句,您还应该看看 array container,这是现代风格的数组。
我正在尝试学习 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++ 的了解还很初级,非常感谢您的帮助,谢谢!
在 [3]
的情况下,函数根据其类型知道数组有多大。引用通常被实现为指向被引用事物的指针,但在 C++ 中,经过大量篇幅来留下实现细节(有时可以实现优化)。引用是其他地方数据的别名,与指针(类似于邮政地址)略有不同。当编译器有长度时迭代很容易,C++ 做正确的事。
在 []
的情况下,这是 C 风格的语法。它不是参考。与int * array
的意思相同。数组的大小既不是编译时类型(在函数内)的一部分,也不是运行时状态(它是单个 int 指针)的一部分。显然没有长度就不可能进行迭代。
基于范围的 for 循环适用于可与 std::begin
和 std::end
一起使用的所有类型。
数组和指针不一样。数组有固定大小,指针没有。因此 std::begin
和 std::end
适用于数组 - 但不适用于指针。这也解释了为什么基于范围的 for 循环适用于一个,但不适用于另一个。
数组也可能退化为指针。例如,当传递给采用指针参数的函数时,就会发生这种情况。或者,当传递给采用不确定大小的数组参数(实际上与指针参数相同)的函数时。发生这种情况时,尺寸信息将再次丢失。
所以这取决于你如何定义函数。第一个函数接受一个数组,第二个函数接受一个指针。这就是为什么第一个保留大小信息并且循环有效的原因。
但是,它限制了函数可以接受的内容。第二个函数可以接受 int b[2]
,而第一个不能。
根据cppreference约arrays and Ranged-based for loop
在 printArray1 中,array 参数是一个 int 引用 的数组,每个一个引用作为参数传递的数组的前 3 个值。
在 printArray2 中,array 参数是一个指针,指向作为参数传递的数组的第一个值。使用它,您可以访问数组的所有值。
最后,它不是指针,只是对 a 数组的引用。 在这种特殊情况下,重要的是要知道对于每次迭代,将对 x 变量执行迭代值的副本。 如果你想防止所有这些复制发生,你应该改为声明一个引用。
示例:
for(int &x : a)
std::cout << x << " ";
顺便说一句,您还应该看看 array container,这是现代风格的数组。