循环通过一个容器
在 C++中,循环遍历序列容器 c
可以使用索引完成,如下所示:
for(size_t i = 0; i < c.size(); ++i) c[i] = 0;
虽然简单,但是这些着作会遇到常见的语义错误,例如错误的比较运算符或错误的索引变量:
for(size_t i = 0; i <= c.size(); ++j) c[i] = 0;
^~~~~~~~~~~~~~^
使用迭代器的所有容器也可以实现循环,具有类似的缺点:
for(iterator it = c.begin(); it != c.end(); ++it) (*it) = 0;
C++ 11 引入了基于范围的 for 循环和 auto
关键字,允许代码变为:
for(auto& x : c) x = 0;
这里唯一的参数是容器 c
,以及一个变量 x
来保存当前值。这可以防止先前指出的语义错误。
根据 C++ 11 标准,底层实现相当于:
for(auto begin = c.begin(), end = c.end(); begin != end; ++begin)
{
// ...
}
在这种实现中,表达式 auto begin =
c.begin(), end = c.end();
强制 begin
和 end
属于同一类型,而 end
永远不会增加,也不会被解除引用。因此,基于范围的 for 循环仅适用于由迭代器/迭代器对定义的容器。C++ 17 标准通过将实现更改为:来放宽此约束:
auto begin = c.begin();
auto end = c.end();
for(; begin != end; ++begin)
{
// ...
}
在这里,begin
和 end
可以是不同类型的,只要它们可以比较不相等。这允许循环通过更多容器,例如由对迭代器/哨兵定义的容器。