循环通过一个容器

在 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(); 强制 beginend 属于同一类型,而 end 永远不会增加,也不会被解除引用。因此,基于范围的 for 循环仅适用于由迭代器/迭代器对定义的容器。C++ 17 标准通过将实现更改为:来放宽此约束:

auto begin = c.begin();
auto end = c.end();
for(; begin != end; ++begin)
{
    // ...
}

在这里,beginend 可以是不同类型的,只要它们可以比较不相等。这允许循环通过更多容器,例如由对迭代器/哨兵定义的容器。