我被困在C ++ Primer中的一段代码中并且已经考虑了超过1小时。代码是
for (auto row : ia)//should use &row here
for (auto col : row)
对它的解释是
我们这样做是为了避免正常的数组转换为指针。因为row不是引用,当编译时 初始化row它将转换每个数组元素(就像数组类型的任何其他对象一样) 指向该数组的第一个元素的指针。结果,在这个循环中行的类型是 INT *。内部for循环是非法的。尽管我们的意图,该循环试图 迭代一个int *。
我知道每次执行for(auto col:row)
时都会与迭代有关。我无法理解的是什么
我们这样做是为了避免正常的数组到指针转换"
是" ia"的形式。我们传入了外循环?它应该是一个指针指向其第一个元素的地址而不是一个"具体的"阵列?那么内循环有什么不对?我认为它应该是与外循环相同的机制..我无法理解Q& A上的帖子。有人请赐教我...我的理解有什么不对......也欢迎一个好的链接!提前谢谢了!
ia的声明是
constexpr size_t rowCnt = 3, colCnt = 4;
int ia[rowCnt][colCnt]; // 12 uninitialized elements
// for each row
for (size_t i = 0; i != rowCnt; ++i) {
// for each column within the row
for (size_t j = 0; j != colCnt; ++j) {
// assign the element's positional index as its value
ia[i][j] = i * colCnt + j;
}
}
答案 0 :(得分:5)
通常,基于范围的for循环声明为:
for ( decl : coll ) {
statement }
如果coll提供了begin()和end()成员,则等效于以下内容:
for (auto _pos=coll.begin(), _end=coll.end(); _pos!=_end; ++_pos )
{
decl = *_pos;
statement
}
或者,如果不匹配,则通过使用全局begin()和end()将coll作为参数来实现以下内容:
for (auto _pos=begin(coll), _end=end(coll); _pos!=_end; ++_pos )
{
decl = *_pos;
statement
}
现在看一下decl = *_pos;
行,这里每次编译器初始化dec时,它会将每个数组元素(与数组类型的任何其他对象一样)转换为指向该数组第一个元素的指针。
在你的情况下,raw的类型将是int *,而next for循环无法工作,因此它变得非法。
答案 1 :(得分:4)
基于范围的for循环基于begin
和end
函数,这些函数不在T*
上工作,但可以在T[N]
上工作。
实施:
for ( range_declaration : range_expression ) loop_statement
是这样的:
{
auto && __range = range_expression ;
for (auto __begin = begin_expr,
__end = end_expr;
__begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
}
由于在外部for循环中,数组会衰减为带有auto row
的指针,因此内部for循环将变为非法。
答案 2 :(得分:2)
Range based for
循环适用于array type
或user defined type
成员函数begin
和end
。
array-to-pointer decay rule
当array
传递给一个取pointer
的函数时,数组会衰减到指针
但是当您使用**reference**
模板时,模板类型会被推断为array type
:
template<typename T>
void foo(T&);
int main() {
int ia[2][2] = {{0,1}, {2,3}};
auto row_val = ia[0]; //int*
auto& row_ref = ia[0]; //int [2]
foo(row_val); //void foo<int*>(int*&)
foo(row_ref); //void foo<int [2]>(int (&) [2])
}
在这里你可以看到(从它创建的错误!!)推导出的row_val
和row_ref
类型不同的
row_val ==> int*
row_ref ==> int [2]
您必须使用for(auto& row: ia)
,row
现在array type
而不是pointer
。因此你可以使用内循环for (auto col : row)
。