使用范围for语句处理多维数组

constexpr size_t rowCnt = 3, colCnt = 4;
int ia[rowCnt][colCnt];
for (size_t i = 0; i != rwoCnt; i++){
    for (size_t j = 0; j != colCnt; j++){
        ia[i][j] = i * colCnt + j;
    }
}

使用范围for语句处理多维数组

C++11中新增了范围for语句,所以前一程序可以简化成如下形式

size_t cnt = 0;
for (auto &row : ia){
    for (auto &col : row){
        col = cnt;
        cnt++;
    }
}

这个循环赋给ia元素的值和之前那个循环是完全相同的,区别之处是通过使用范围 for语句把管理数组索引的任务交给了系统来完成。

因为要改变元素的值,所以得把控制变量 row和col声明成引用类型。

第一个for循环遍历ia的所有元素,这些元素是大小为 4 的数组,因此 row的类型就应该是含有4个整数的数组的引用。

第二个 for 循环遍历那些4元素数组中的某一个,因此col的类型是整数的引用。每次迭代把 cnt 的值赋给 ia 的当前元素,然后将 cnt 加 1。

在上面的例子中,因为要改变数组元素的值,所以我们选用引用类型作为循环控制变量,但其实还有一个深层次的原因促使我们这么做。举一个例子,考虑如下的循环∶

for (const auto &row : ia){
    for (auto col : row){
        cout << col << endl;
    }
}

这个循环中并没有任何写操作,可是我们还是将外层循环的控制变量声明成了引用类型,这是为了避免数组被自动转成指针。假设不用引用类型,则循环如下述形式∶

for (auto row : ia){
    for (auto col : row){
        cout << col << endl;
    }
}

程序将无法通过编译。这是因为,像之前一样第一个循环遍历 ia的所有元素,注意这些元素实际上是大小为 4的数组。

因为 row不是引用类型,所以编译器初始化row 时会自动将这些数组形式的元素(和其他类型的数组一样)转换成指向该数组内首元素的指针。这样得到的 row 的类型就是 int * ,显然内层的循环就不合法了,编译器将试图在一个 int * 内遍历,这显然和程序的初衷相去甚远。

posted @ 2021-01-22 16:27  DearLeslie  阅读(289)  评论(0编辑  收藏  举报