是否应该使用循环范围而不是向量上的迭代器?

时间:2016-02-15 19:18:32

标签: c++ for-loop vector iterator

给定一个向量,vc,可以迭代一个范围为:

的向量
for (auto c : vc)
    std::cout << c;

或使用迭代器:

for (auto it = vc.cbegin(); it != vc.cend(); ++it)
    std::cout << *it;

是否存在使用一种方法而不是另一种方法的功能性原因,或者仅仅是风格问题?

4 个答案:

答案 0 :(得分:4)

这或多或少是一种风格问题,但请考虑这种方式; range-for循环比显式迭代器使用更简洁。你编写的代码越少,出错的地方就越少。

答案 1 :(得分:4)

从性能的角度来看,并没有什么区别。正如Bjarne Stroustrup在他的书中所写的C ++编程语言第4版:

  

最简单的循环是一个范围的陈述;它只是让程序员访问每个元素   范围。

作为KISS原则的粉丝,我倾向于更简单的结构而不是更复杂的结构。但是,它实际上归结为您想要实现的目标。在同一本书中,Bjarne揭示了为什么范围换环设计简单:

  

请注意,range-for循环是一个故意简单的构造。对于   例如,使用它你不能同时触摸两个元素   不能同时有效地遍历两个范围。为此,我们需要   一般的陈述。

因此,有些情况下你不能使用range-for循环,你必须驻留在经典的for语句中。

底线尽可能使用range-for循环,因为它更简单,更易读。

答案 2 :(得分:3)

您的两个示例之间存在两个实质性差异。首先,auto c会创建每个元素的副本,因此如果您不想创建不必要的副本,请使用auto const& c。其次,范围for是根据非const迭代器实现的,但是你的for循环使用const迭代器。如果vc是标准容器并不重要,但是某些容器(例如Qt中的容器)使用内部共享指针实现写时复制语义,在这种情况下使用非const迭代器将不必要地复制整个容器。您可以通过使用C ++ 17 for来避免这种情况并仍然使用漂亮的范围std::as_const语法:

for (auto const& c : std::as_const(vc))
    std::cout << c;

如果您的环境无法提供,您可以轻松实现自己的as_const版本。

答案 3 :(得分:2)

对于您的具体示例,它们是等效的。而且由于它们是等价的,你自然希望选择最短版本,这也是最容易出错的版本 - 免费。

还建议将range-for循环缩短为:

for ( var : range )

其中var将具有类型auto&&(也称为转发/通用引用),这是引用对象的最佳方式。只需auto var即可复制每个元素,这可能并不便宜。不幸的是,它没有通过。

您通常不会直接使用迭代器,所以范围 - 您应该是您的首选。显式迭代器也可能指向超出范围的元素,因为您可以在范围内自由移动,从而导致未定义的行为。