Namespaces
Variants

std::for_each_n

来自 zh.cppreference.net
 
 
算法库
受约束算法和范围算法 (C++20)
受约束算法,例如 ranges::copy、ranges::sort、...
排序和相关操作
划分操作
(C++11)    

排序操作
二分搜索操作
(在已划分的范围上)
集合操作(在已排序范围上)
合并操作(在已排序范围上)
堆操作
最小/最大操作
(C++11)
(C++17)
字典序比较操作
排列操作


 
在标头中定义 <algorithm>
template< class InputIt, class Size, class UnaryFunc >
InputIt for_each_n( InputIt first, Size count, UnaryFunc f );
(1) (constexpr (C++20 起))
template< class ExecutionPolicy,
          class ForwardIt, class Size, class UnaryFunc >
ForwardIt for_each_n( ExecutionPolicy&& policy,
                      ForwardIt first, Size count, UnaryFunc f );
(2) (C++17 起)

将给定的可调用对象 f 应用于目标范围 [first, std::next(first, count)) 中的每个元素。如果 f 返回结果,则忽略该结果。

1) f 按顺序应用,从 first 开始。
如果 UnaryFunc 不是 MoveConstructible,则行为未定义。
2) f 可能不按顺序应用。该算法根据 policy 执行。
与其他 并行算法不同,for_each_n 不允许对目标范围中的元素进行任意复制。
此重载仅在以下表达式的值为 true 时参与重载决议:

std::is_execution_policy_v<std::decay_t<ExecutionPolicy>>

(C++20 前)

std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>

(C++20 起)
如果 UnaryFunc 不是 CopyConstructible,则行为未定义。

如果 count >= 0 不是 true,则行为未定义。

参数

first - 目标范围的起始
count - 目标范围内的元素数
f - 函数对象,应用于元素

函数签名应等价于以下形式:

void fun(const Type &a);

签名不需要有 const &。
类型 Type 必须使得 InputIt 类型的对象可以被解引用然后隐式转换为 Type。

​

policy - 要使用的 执行策略
类型要求
-
InputIt 必须满足 老式输入迭代器(LegacyInputIterator) 的要求。
-
ForwardIt 必须满足 老式向前迭代器(LegacyForwardIterator) 的要求。
-
Size 必须可转换为整数类型。

返回值

std::next(first, count)

复杂度

恰好 count 次应用 f。

异常

2) 在执行过程中:
  • 如果并行化所需的临时内存资源不可用,则抛出 std::bad_alloc。
  • 如果在通过算法参数访问对象时抛出未捕获的异常,则行为由执行策略决定(对于 标准策略,将调用 std::terminate)。

注意

如果迭代器类型 (InputIt/ForwardIt) 是可变的,则 f 可能会修改目标范围内的元素。

可能的实现

另请参阅 libstdc++、libc++ 和 MSVC stdlib 中的实现。

template<class InputIt, class Size, class UnaryFunc>
InputIt for_each_n(InputIt first, Size count, UnaryFunc f)
{
    for (Size i = 0; i < count; ++first, (void) ++i)
        f(*first);
    
    return first;
}

示例

#include <algorithm>
#include <iostream>
#include <vector>

void println(const auto& v)
{
    for (auto count{v.size()}; const auto& e : v)
        std::cout << e << (--count ? ", " : "\n");
}

int main()
{
    std::vector<int> vi{1, 2, 3, 4, 5};
    println(vi);
    
    std::for_each_n(vi.begin(), 3, [](auto& n) { n *= 2; });
    println(vi);
}

输出:

1, 2, 3, 4, 5
2, 4, 6, 4, 5

缺陷报告

下列行为变更的缺陷报告已追溯应用于之前发布的 C++ 标准。

DR 应用于 已发布的行为 正确行为
LWG 3213
(P1718R2)
C++17 Size 不需要可转换为整数类型 需要

参阅

将函数对象应用于序列的前 N 个元素
(算法函数对象)
将一元 函数对象应用于来自 范围
的元素(函数模板 & 算法函数对象)
将函数应用于元素范围,将结果存储到目标范围
(函数模板 & 算法函数对象)
基于范围的for for 循环(C++11) 在范围上执行循环