std::for_each
定义于头文件 <algorithm> |
||
template< class InputIt, class UnaryFunc > UnaryFunc for_each( InputIt first, InputIt last, UnaryFunc f ); |
(1) | (constexpr 自 C++20 起) |
template< class ExecutionPolicy, class ForwardIt, class UnaryFunc > void for_each( ExecutionPolicy&& policy, |
(2) | (自 C++17 起) |
将给定的 一元函数对象 f 应用于解引用范围 迭代器 范围 [
first,
last)
中的每个 迭代器 的结果。如果 f 返回结果,则忽略该结果。
std::is_execution_policy_v<std::decay_t<ExecutionPolicy>> 为 true。 |
(C++20 前) |
std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>> 为 true。 |
(自 C++20 起) |
如果迭代器类型 (InputIt
/ForwardIt
) 是可变的,则 f 可以通过解引用的迭代器修改 范围 的元素。
与其余并行算法不同,即使序列中的元素是 可平凡复制 (TriviallyCopyable),for_each
也不允许复制它们。
目录 |
[编辑] 参数
first, last | - | 一对迭代器,定义了 范围,函数对象将应用于该范围的元素 |
policy | - | 要使用的 执行策略 |
f | - | 函数对象,将应用于解引用 范围 [ first, last) 中每个迭代器的结果函数的签名应等效于以下内容 void fun(const Type &a); 签名不需要具有 const &。 |
类型要求 | ||
-InputIt 必须满足 LegacyInputIterator 的要求。 | ||
-ForwardIt 必须满足 LegacyForwardIterator 的要求。 |
[编辑] 返回值
[编辑] 复杂度
正好 std::distance(first, last) 次 f 的应用。
[编辑] 异常
具有名为 ExecutionPolicy
的模板参数的重载报告错误如下
- 如果作为算法一部分调用的函数的执行抛出异常,并且
ExecutionPolicy
是 标准策略 之一,则调用 std::terminate。对于任何其他ExecutionPolicy
,行为是实现定义的。 - 如果算法无法分配内存,则抛出 std::bad_alloc。
[编辑] 可能的实现
另请参见 libstdc++、libc++ 和 MSVC stdlib 中的实现。
template<class InputIt, class UnaryFunc> constexpr UnaryFunc for_each(InputIt first, InputIt last, UnaryFunc f) { for (; first != last; ++first) f(*first); return f; // implicit move since C++11 } |
[编辑] 注解
对于重载 (1),f 可以是有状态的函数对象。返回值可以被视为批量操作的最终状态。
对于重载 (2),可能会创建 f 的多个副本以执行并行调用。由于并行化通常不允许高效的状态累积,因此不返回值。
[编辑] 示例
以下示例使用 lambda 表达式 来递增向量的所有元素,然后在一个函数对象 (又名“仿函数”) 中使用重载的 operator()
来计算它们的总和。请注意,为了计算总和,建议使用专用算法 std::accumulate。
#include <algorithm> #include <iostream> #include <vector> int main() { std::vector<int> v{3, -4, 2, -8, 15, 267}; auto print = [](const int& n) { std::cout << n << ' '; }; std::cout << "before:\t"; std::for_each(v.cbegin(), v.cend(), print); std::cout << '\n'; // increment elements in-place std::for_each(v.begin(), v.end(), [](int &n) { n++; }); std::cout << "after:\t"; std::for_each(v.cbegin(), v.cend(), print); std::cout << '\n'; struct Sum { void operator()(int n) { sum += n; } int sum {0}; }; // invoke Sum::operator() for each element Sum s = std::for_each(v.cbegin(), v.cend(), Sum()); std::cout << "sum:\t" << s.sum << '\n'; }
输出
before: 3 -4 2 -8 15 267 after: 4 -3 3 -7 16 268 sum: 281
[编辑] 缺陷报告
以下行为更改缺陷报告被追溯应用于先前发布的 C++ 标准。
DR | 应用于 | 已发布行为 | 正确行为 |
---|---|---|---|
LWG 475 | C++98 | 不清楚 f 是否可以修改元素 正在迭代的序列 ( for_each 被归类为“非修改序列操作”) |
明确 (如果 迭代器类型是可变的,则允许) |
LWG 2747 | C++11 | 重载 (1) 返回 std::move(f) | 返回 f (隐式移动) |
[编辑] 参见
transform - cppreference.cn (函数模板) | |
(C++17) |
for_each_n - cppreference.cn (函数模板) |
将一元函数对象应用于来自 范围 的元素 (算法函数对象) | |
for_each_n - cppreference.cn (算法函数对象) | |
范围-for 循环(C++11) |
对范围执行循环 |