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