给定一个向量,vc,
可以迭代一个范围为:
for (auto c : vc)
std::cout << c;
或使用迭代器:
for (auto it = vc.cbegin(); it != vc.cend(); ++it)
std::cout << *it;
是否存在使用一种方法而不是另一种方法的功能性原因,或者仅仅是风格问题?
答案 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
即可复制每个元素,这可能并不便宜。不幸的是,它没有通过。
您通常不会直接使用迭代器,所以范围 - 您应该是您的首选。显式迭代器也可能指向超出范围的元素,因为您可以在范围内自由移动,从而导致未定义的行为。