嗨,我正在使用 2D 和 1D 数组C++并使用范围来访问元素。我使用的代码如下:
对于 2D 阵列
int ia[3][4] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
for (auto& row : ia) {
for (auto col : row) {
cout << col << endl;
}
}
对于 ID 数组
int base_array[2] = { 1, 2 };
for (auto p : base_array) {
std::cout << p << std::endl;
}
因此,正如我们在 2D 数组的外部循环范围中看到的那样,控制变量行必须是引用类型,这样就不会发生自动数组到指针的转换,我们可以循环访问本身是大小为 4 的数组的元素。但是在 1D 数组中,我们不使用控制变量p作为参考类型,即使这样,我们也能够遍历 1D 数组。我的问题是为什么在一维数组中没有发生数组到指针的转换?如果没有引用类型的控制变量,它是如何工作的?也就是说,为什么(如何)p
int
类型而不是在一维数组情况下int*
,而如果我们省略控制变量行中的参考符号,它将变成 int*,但是当我们在变量行前面包含参考符号时,它将变成数组类型。为什么会有这种行为差异?
在您的 1D 情况下,base_array 不会衰减,因为它与 for 循环存在于同一范围内。因此,基于范围的 for 可以正确计算出其范围。真的是这样,1D没有衰减。如果您尝试通过函数传递该 1D 数组,您会发现基于范围的 for 变得不可能,因为它会衰减,除非您将其作为引用传递。
在你的2D情况下,如果你允许row
衰减到int*
,嵌套的for不能再假设你必须意味着一个数组。因此,您可以使用auto&
来保留类型,允许嵌套的 for 知道您在说什么。
为什么在一维数组中没有发生数组到指针的转换?
在1D数组的情况下,数组的元素是int
对象,而在2D数组的情况下,数组的元素是"int
"对象的数组。
如果不使用引用,int
数组将衰减到指针。因此,对第一种情况使用参考是合适的。
情况1(行前面没有参考符号)
对于外部循环,循环变量row
初始化为ia
的第一个元素,该元素本身就是一个数组,因此将进行数组到指针的转换,并且row
将变得int*
。由于我们无法循环int*
,当我们尝试在内部 for 循环中这样做时,我们会得到一个错误。
情况2(行前面有参考符号)
当我们在row
的字体中添加引用符号时,该数组到指针的转换将不再发生,row
将是数组类型而不是指针类型,并且由于我们可以循环遍历数组,因此这种情况将起作用。
来自 C++ 17 标准(10.1.7.4.1 占位符类型扣除)
4 如果占位符是自动类型说明符,则推导的类型 T0 替换 T 是使用模板参数的规则确定的 演绎。通过将 auto 的出现次数替换为 要么是新发明的类型模板参数 U,要么是 初始化是复制列表初始化,使用 标准::initializer_list。使用模板参数的规则推导出 U 的值 从函数调用中扣除 (17.8.2.1)
和(17.8.2.1 从函数调用中推导模板参数)
2 如果 P 不是引用类型:
(2.1) — 如果 A 是数组类型,则由 数组到指针的标准转换 (7.2) 用于代替 A 表示 类型扣除;否则
因此,如果您不会在循环中使用引用的类型
for (auto row : ia)
然后变量行的类型将被int *
也就是说,它将是一个指针类型,你不能使用基于范围的 for 循环。