在C++11中,所有元素都有两个循环(基于for和for_each的范围)。是否有理由偏爱另一个或者是否存在更适合的情况?
for (auto& elem: container) {
// do something with elem
}
std::for_each(container.begin(), container.end(),
[](Elem& elem) {
// do something with elem
});
我的想法是,第一个更简单,类似于其他语言中基于范围的循环,而第二个也适用于不是完整容器的序列,第二个更类似于其他std
- 算法。
答案 0 :(得分:31)
基于范围的for
显然更易于读写。它专门用于完成这项任务。
编辑:您可以在不滥用异常的情况下中断范围。 (虽然std::find_if
替换std::for_each
也允许这样做。)
std::for_each
是实际上基于范围的替代方案,允许您选择特定的begin
和end
值而不是整个容器。 (编辑:这可以使用提供range
和begin
成员的简单end
类进行攻击,例如Boost提供的。)
当使用高阶函数时,for_each
也可能更优雅:它可以用作bind
的参数,第三个参数已经是一个仿函数。
主要是风格问题。大多数读者可能更喜欢看for ( auto &a : b )
,现在大多数实现都支持它。
答案 1 :(得分:11)
std::for_each
返回循环内部使用的仿函数,因此它提供了一个干净的机制来收集有关序列中元素的一些信息。基于for循环的范围只是一个循环,因此在循环外使用的任何状态都必须在该范围之外声明。在你的例子中,如果循环的目的是改变序列的每个元素,那么根本没有太大的区别。但是如果你没有使用for_each
的返回值,那么你可能最好使用简单的循环。顺便说一句,基于范围的循环也适用于C风格的数组和std :: strings。
这是使用for_each
的返回值的示例,尽管它不是非常富有想象力或有用的。这只是为了说明这个想法。
#include <iostream>
#include <array>
#include <algorithm>
struct Foo {
void operator()(int i) { if (i > 4) sum += i;}
int sum{0};
};
int main() {
std::array<int, 10> a{1,2,3,4,5,6,7,8,9,10};
Foo foo = std::for_each(a.begin(), a.end(), Foo());
std::cout << "Sum " << foo.sum << "\n";
}