为什么 auto 在 C++ 中的二维和一维数组中的 "range for" 中的工作方式不同
Why does auto works differently in "range for" in 2D and 1D arrays in C++
您好,我正在使用 C++ 中的二维和一维数组,并使用 range for 来访问 elements.The 我正在使用的代码如下:
对于二维数组
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;
}
所以我们可以在二维数组的外部范围for循环中看到,控制变量row必须是引用类型,这样数组到指针的自动转换就不会发生我们可以循环遍历本身是大小为 4 的数组的元素。但是在一维数组中,我们没有使用控制变量 p 作为引用类型,即使这样我们也能够遍历通过一维数组。我的问题是为什么在一维数组中没有进行数组到指针的转换?如果控制变量不是引用类型,它是如何工作的?也就是说,为什么(如何)是 int
类型的 p
而不是一维数组情况下的 int*
而如果我们在控制变量中省略引用符号 row 然后它会变成一个 int* 但是当我们在变量 row 前面包含引用符号时它会变成一个数组类型。为什么会有这种行为差异?
在您的 1D 情况下,base_array 不会衰减,因为它存在于与 for 循环相同的范围内。所以基于范围的 for 可以正确地计算出它的范围。就是这样,1D 没有衰减。如果您曾尝试通过函数传递该一维数组,您会发现基于范围的 for 变得不可能,因为它会衰减,除非您将它作为参考传递。
在您的 2D 情况下,如果您允许 row
衰减到 int*
,则嵌套 for 不能再假定您必须指的是数组。因此,您通过使用 auto&
来保留类型,让嵌套的 for 知道您在说什么。
why in the 1D array the array to pointer conversion is not taking place?
在一维数组的情况下,数组的元素是 int
个对象,而在二维数组的情况下,数组的元素是“int
”对象的数组。
如果不使用引用,int
的数组将衰减为指针。因此,第一种情况使用参考是合适的。
来自 C++ 17 标准(10.1.7.4.1 占位符类型推导)
4 If the placeholder is the auto type-specifier, the deduced type T0
replacing T is determined using the rules for template argument
deduction. Obtain P from T by replacing the occurrences of auto with
either a new invented type template parameter U or, if the
initialization is copy-list-initialization, with
std::initializer_list. Deduce a value for U using the rules of template argument
deduction from a function call (17.8.2.1)
和(17.8.2.1 从函数调用中推导模板参数)
2 If P is not a reference type:
(2.1) — If A is an array type, the pointer type produced by the
array-to-pointer standard conversion (7.2) is used in place of A for
type deduction; otherwise,
因此,如果您不在循环中使用引用类型
for (auto row : ia)
那么变量 row 的类型将是 int *
即它将是一个指针类型,您不能使用基于范围的 for 循环。
案例 1(行前面没有参考符号)
对于外部循环,循环变量 row
被初始化为 ia
的第一个元素,它本身是一个数组,因此数组到指针的转换将发生 row
会变成int*
。由于我们无法循环遍历 int*
,因此当我们尝试在内部 for 循环中这样做时会出现错误。
案例 2(行前有参考符号)
当我们添加 row
的引用符号信息时,数组到指针的转换将不再发生,row
将是数组类型而不是指针类型,因为我们可以循环通过一个数组,因此这种情况会起作用。
您好,我正在使用 C++ 中的二维和一维数组,并使用 range for 来访问 elements.The 我正在使用的代码如下:
对于二维数组
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;
}
所以我们可以在二维数组的外部范围for循环中看到,控制变量row必须是引用类型,这样数组到指针的自动转换就不会发生我们可以循环遍历本身是大小为 4 的数组的元素。但是在一维数组中,我们没有使用控制变量 p 作为引用类型,即使这样我们也能够遍历通过一维数组。我的问题是为什么在一维数组中没有进行数组到指针的转换?如果控制变量不是引用类型,它是如何工作的?也就是说,为什么(如何)是 int
类型的 p
而不是一维数组情况下的 int*
而如果我们在控制变量中省略引用符号 row 然后它会变成一个 int* 但是当我们在变量 row 前面包含引用符号时它会变成一个数组类型。为什么会有这种行为差异?
在您的 1D 情况下,base_array 不会衰减,因为它存在于与 for 循环相同的范围内。所以基于范围的 for 可以正确地计算出它的范围。就是这样,1D 没有衰减。如果您曾尝试通过函数传递该一维数组,您会发现基于范围的 for 变得不可能,因为它会衰减,除非您将它作为参考传递。
在您的 2D 情况下,如果您允许 row
衰减到 int*
,则嵌套 for 不能再假定您必须指的是数组。因此,您通过使用 auto&
来保留类型,让嵌套的 for 知道您在说什么。
why in the 1D array the array to pointer conversion is not taking place?
在一维数组的情况下,数组的元素是 int
个对象,而在二维数组的情况下,数组的元素是“int
”对象的数组。
如果不使用引用,int
的数组将衰减为指针。因此,第一种情况使用参考是合适的。
来自 C++ 17 标准(10.1.7.4.1 占位符类型推导)
4 If the placeholder is the auto type-specifier, the deduced type T0 replacing T is determined using the rules for template argument deduction. Obtain P from T by replacing the occurrences of auto with either a new invented type template parameter U or, if the initialization is copy-list-initialization, with std::initializer_list. Deduce a value for U using the rules of template argument deduction from a function call (17.8.2.1)
和(17.8.2.1 从函数调用中推导模板参数)
2 If P is not a reference type:
(2.1) — If A is an array type, the pointer type produced by the array-to-pointer standard conversion (7.2) is used in place of A for type deduction; otherwise,
因此,如果您不在循环中使用引用类型
for (auto row : ia)
那么变量 row 的类型将是 int *
即它将是一个指针类型,您不能使用基于范围的 for 循环。
案例 1(行前面没有参考符号)
对于外部循环,循环变量 row
被初始化为 ia
的第一个元素,它本身是一个数组,因此数组到指针的转换将发生 row
会变成int*
。由于我们无法循环遍历 int*
,因此当我们尝试在内部 for 循环中这样做时会出现错误。
案例 2(行前有参考符号)
当我们添加 row
的引用符号信息时,数组到指针的转换将不再发生,row
将是数组类型而不是指针类型,因为我们可以循环通过一个数组,因此这种情况会起作用。