首选标准用途:基于范围或std :: for_each

时间:2012-04-03 13:34:58

标签: c++ coding-style c++11

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 - 算法。

2 个答案:

答案 0 :(得分:31)

  1. 基于范围的for显然更易于读写。它专门用于完成这项任务。

    编辑:您可以在不滥用异常的情况下中断范围。 (虽然std::find_if替换std::for_each也允许这样做。)

  2. 具有讽刺意味的是,
  3. std::for_each是实际上基于范围的替代方案,允许您选择特定的beginend值而不是整个容器。 (编辑:这可以使用提供rangebegin成员的简单end类进行攻击,例如Boost提供的。)

    当使用高阶函数时,for_each也可能更优雅:它可以用作bind的参数,第三个参数已经是一个仿函数。

  4. 主要是风格问题。大多数读者可能更喜欢看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";
}