对于基于范围的for循环而言,冒号后面的表达式只会被执行一次。
#include <iostream>
#include <vector>
std::vector<int> arr = { 1, 2, 3, 4, 5 };
std::vector<int>& get_range(void)
{
std::cout << "get_range ->: " << std::endl;
return arr;
}
int main(void)
{
for (auto val : get_range())
{
std::cout << val << std::endl;
}
getchar();
return 0;
}
运行结果:
get_range ->:
1
2
3
4
5
错误用法示范:
#include <iostream>
#include <vector>
int main(void)
{
std::vector<int> arr = { 1, 2, 3, 4, 5 };
int i = 0;
for (auto val : arr)
{
std::cout << val << std::endl;
arr.push_back(0); //扩大容器
}
getchar();
return 0;
}
输出结果:
1
-572662307
-572662307
-572662307
-572662307
同普通的for循环一样,在迭代时修改容器很可能会引起迭代器失效,导致一些意料之外的结果。
换成普通的for循环:
#include <iostream>
#include <vector>
int main(void)
{
std::vector<int> arr = { 1, 2, 3, 4, 5 };
auto && __range = (arr);
for (auto __begin = __range.begin(), __end = __range.end();
__begin != __end; ++__begin)
{
auto val = *__begin;
std::cout << val << std::endl;
arr.push_back(0); //扩大容器
}
getchar();
return 0;
}
基于范围的for循环倾向于在循环开始之前确定好迭代的范围,而不是在每次迭代之前都去调用一次arr.end();
良好的编程习惯是尽量不要再迭代器过程中修改迭代器的容器。但是实际情况要求我们不得不这样的时候,通过理解基于范围的for循环的这个特点,就可以方便地分析每次迭代的结果,提前避免算法的错误。