跳到主要内容

std::for_each() 算法

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

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

将给定函数应用于范围内的所有元素。

  • (1) 将给定函数对象 f 按顺序应用于范围 [first, last) 中每个迭代器解引用的结果。

  • (2)(1),但根据策略执行。

    警告

    不保证函数会按顺序应用于元素。

    重载决议

    这些重载只有在 std::is_execution_policy_v<std::decay_t<ExecutionPolicy>>  (直到 C++20) std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>  (从 C++20 开始)true 时才参与重载决议。

对于这两种重载,如果迭代器类型 (InputIt/ForwardIt) 是可变的,f 可能会修改范围的元素。如果 f 返回结果,则结果将被忽略。

警告

与其余并行算法不同,for_each 不允许复制序列中的元素,即使它们是 TriviallyCopyable

参数

first
last

要应用函数的元素范围。

policy

要使用的执行策略。有关详细信息,请参阅执行策略

f

函数对象,应用于范围的每个元素。

函数的签名应与以下内容等效

void fun(const Type& a);
  • 签名不需要包含 const&
  • 类型 Type 必须是这样的,即 InputIt 类型的对象可以被解引用,然后隐式转换为 Type

类型要求

InputItLegacyInputIterator
ForwardItLegacyForwardIterator
UnaryFunctionMoveConstructible
UnaryFunction2CopyConstructible

返回值

  • (1) - f (直到 C++11) std::move(f) (从 C++11 开始)
  • (2) - (无)

复杂度

给定 Nstd::distance(first, last)

精确执行 f N 次。

异常

带有模板参数 ExecutionPolicy 的重载报告错误如下

  • 如果作为算法一部分调用的函数在执行过程中抛出异常,并且 ExecutionPolicy标准策略 之一,则会调用 std::terminate。对于任何其他 ExecutionPolicy,行为是 实现定义的.
  • 如果算法未能分配内存,则抛出 std::bad_alloc

可能的实现

for_each (1)

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

return f; // implicit move since C++11
}

示例

Main.cpp
#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
本文来源于此 CppReference 页面。它可能经过了修改以进行改进或满足编辑偏好。点击“编辑此页面”查看本文档所做的所有更改。
悬停查看原始许可证。

std::for_each() 算法

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

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

将给定函数应用于范围内的所有元素。

  • (1) 将给定函数对象 f 按顺序应用于范围 [first, last) 中每个迭代器解引用的结果。

  • (2)(1),但根据策略执行。

    警告

    不保证函数会按顺序应用于元素。

    重载决议

    这些重载只有在 std::is_execution_policy_v<std::decay_t<ExecutionPolicy>>  (直到 C++20) std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>  (从 C++20 开始)true 时才参与重载决议。

对于这两种重载,如果迭代器类型 (InputIt/ForwardIt) 是可变的,f 可能会修改范围的元素。如果 f 返回结果,则结果将被忽略。

警告

与其余并行算法不同,for_each 不允许复制序列中的元素,即使它们是 TriviallyCopyable

参数

first
last

要应用函数的元素范围。

policy

要使用的执行策略。有关详细信息,请参阅执行策略

f

函数对象,应用于范围的每个元素。

函数的签名应与以下内容等效

void fun(const Type& a);
  • 签名不需要包含 const&
  • 类型 Type 必须是这样的,即 InputIt 类型的对象可以被解引用,然后隐式转换为 Type

类型要求

InputItLegacyInputIterator
ForwardItLegacyForwardIterator
UnaryFunctionMoveConstructible
UnaryFunction2CopyConstructible

返回值

  • (1) - f (直到 C++11) std::move(f) (从 C++11 开始)
  • (2) - (无)

复杂度

给定 Nstd::distance(first, last)

精确执行 f N 次。

异常

带有模板参数 ExecutionPolicy 的重载报告错误如下

  • 如果作为算法一部分调用的函数在执行过程中抛出异常,并且 ExecutionPolicy标准策略 之一,则会调用 std::terminate。对于任何其他 ExecutionPolicy,行为是 实现定义的.
  • 如果算法未能分配内存,则抛出 std::bad_alloc

可能的实现

for_each (1)

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

return f; // implicit move since C++11
}

示例

Main.cpp
#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
本文来源于此 CppReference 页面。它可能经过了修改以进行改进或满足编辑偏好。点击“编辑此页面”查看本文档所做的所有更改。
悬停查看原始许可证。