C++11 新标准引入了范围for语句,用来方便地遍历一个容器或其他序列。其语法形式是:
for(declaration : expression)
statement
expression表示必须是一个序列,比如用花括号括起来的初始值列表、数组、或者 vector 或 string 等类型的对象。这些类型的共同特点是拥有能够返回迭代器的 begin 和 end 成员。
declaration定义一个变量,auto 确保类型相容,让编译器帮我们找到合适的类型。如果需要进行修改的操作,需用声明称引用类型,因为默认是按值传递。
vector<int> v = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
for (auto &r : v) {
r*= 2; // v 中的所有值都翻倍
}
//与之等价的传统 for 语句
for (auto beg = v.begin(); beg != v.end(); ++beg) {
auto &r = *beg; // r 必须为引用类型, * 2 的写操作才有效
r *= 2;
}
看到上面的等价传统 for 语句,就能够明白为什么在循环体中不能对 vec 进行增删操作,并且如果要写操作,需要声明引用。
还有一点需要强调,在使用范围 for 语句遍历多维数组时,也必须声明为引用类型,不然编译通过不了,因为 auto 默认推断的数组元素是指向数组首元素指针。
int n[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
for (auto &row : n) // row 必须是引用,才能保证 row 是 int[] , 而不是 int*
for (auto &col : row)
cout << col << endl;