【C++】泛型算法之std::for_each

std::for_each用于逐个遍历容器元素,它对迭代器区间[first, last)所指的每一个元素,执行由单参数函数对象f所定义的操作。它是for循环的一种替代方案。

尽管,我们仍可以使用for循环进行一个容器元素的遍历,但是std::for_each额外给我们提供了一种途径,而且丰富了更多的语义信息,在并行上会比朴素的for循环更有优势。


std::for_each

如需使用std::for_each,需要引入头文件:

#include 

std::for_each函数定义:

template< class InputIt, class UnaryFunction >
UnaryFunction for_each(InputIt first, InputIt last, UnaryFunction f);

函数意义:按顺序应用给定的可调用对象f[first, last)范围内每个迭代器的结果

函数参数:

  • first、last:应用函数的范围
  • f:可调用对象,应用于范围[first, last]内每个迭代器的结果

对于可调用对象,其函数签名应等同于以下内容:

void fun(const Type &a);

其中,唯一参数也不一定要有const &,但该可调用对象的返回值必须为void

函数返回值:传入的可调用对象的最终状态(C++11后,该返回值为右值)

一般情况下,获得返回值常用于可调用对象为函数对象时(重载了()运算符类型的对象)。

根据语义,std::for_each可能的一种实现是:

template<class InputIt, class UnaryFunction>
constexpr UnaryFunction for_each(InputIt first, InputIt last, UnaryFunction f)
{for (; first != last; ++first) {f(*first);}return std::move(f);
}

std::for_each的优越性

std::for_each更明确了整个循环语义,有利于编译器优化。它偏向于函数式编程,就是老老实实从first迭代到end,没有中途退出循环的break,没有直接跳下一步循环的continue

这个语义清清楚楚,编译器可以尽情优化。相反,如果使用传统的for循环,或者C++11的range-based for,都无法让编译器相信半途中是否会来个break/continue这样的操作。

也就是说,编译器可以从for_each里获得更多的语义。而for循环把这些语义全搞丢了!

因此,std::for_each可以支持并行操作。C++17开始有并行的std::for_each重载了,目前msvc和gcc已经实现,clang还没有实现

template< class ExecutionPolicy, class ForwardIt, class UnaryFunction2 >
void for_each(ExecutionPolicy&& policy, ForwardIt first, ForwardIt last, UnaryFunction2 f);

该函数:应用给定的可调用对象f到[first, last)范围内每个迭代器的结果(不必按顺序),按照policy执行算法

policy指的是允许的并行类型,具体的类型种类可以参考:

  • std::execution::seq, std::execution::par, std::execution::par_unseq, std::execution::unseq

std::for_each实例

#include 
#include 
#include class Sum {public:Sum() : sum(0) {}~Sum() {}void operator()(int n) { sum += n; }int sum;
};int main()
{std::vector<int> nums{6, 8, 4, 10, 2, 12};auto print = [](int n) {std::cout << n << " ";};std::for_each(nums.begin(), nums.end(), print);                   // 打印std::cout << std::endl;std::for_each(nums.begin(), nums.end(), [](int &n) {              // 每个数++++n;});std::for_each(nums.begin(), nums.end(), print);                   // 打印std::cout << std::endl;Sum s = std::for_each(nums.begin(), nums.end(), Sum());           // 求和std::cout << s.sum << std::endl;int sum = 0;std::for_each(nums.begin(), nums.end(), [&sum](int n) {           // 求和sum += n;});std::cout << sum << std::endl;return 0;
}

编译并运行这段代码:

yngzmiao@yngzmiao-virtual-machine:~/test/foreach$ ./main 
6 8 4 10 2 12 
7 9 5 11 3 13 
48
48

相关阅读

  • C++ STL中 for_each 算法存在的意义是什么?
  • std::for_each - cppreference.com
  • C++中std::for_each的使用


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部