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

ste*_*anv 46 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
              });
Run Code Online (Sandbox Code Playgroud)

我的想法是第一个更简单,类似于其他语言中基于范围的循环,而第二个也适用于不完整容器的序列,第二个更类似于其他std算法.

Pot*_*ter 33

  1. 基于范围的for读取和写入显然更简单.它专门用于此任务.

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

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

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

主要是风格问题.大多数读者可能更愿意看到for ( auto &a : b ),大多数实现现在支持它.

  • 您可能只想添加范围 - 允许中断和继续. (7认同)
  • @juanchopanza:当然,如果你使用`Range`容器(例如`Boost.Range`),那么这个优势是没有实际意义的. (6认同)
  • 实际上,您可以在+1中选择范围for_each,这一点非常有力。 (2认同)
  • @Klaim:`for_each`通过lambda(或函数或函数)的`return`支持`continue`.对于类似"break"的行为,可以使用`find_if`或其他更合适的算法. (2认同)

jua*_*nza 12

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";
}
Run Code Online (Sandbox Code Playgroud)

  • +1,但请注意,无论如何都无法查询lambda仿函数; 获得辅助状态将通过捕获变量完成,捕获变量在任一构造中都可以正常工作. (3认同)
  • @juanchopanza:的确,幸运的是,C++ 03也改善了这种情况.在C++ 03中,如果你得到一个完整的结果(因为副本),则没有指定,而在C++ 11中,只使用了移动操作. (2认同)

小智 6

从C++17开始,std::for_each还支持执行策略

例如,通过编写下面的代码,您可以告诉编译器该循环可以并行化:

std::vector<int> v = {1, 2, 3};
std::for_each(std::execution::par, v.begin(), v.end(), [](int &n){ ++n; });
Run Code Online (Sandbox Code Playgroud)

您不能对基于范围的for循环执行相同的操作。