名稱空間
變體
操作

std::for_each

來自 cppreference.com
< cpp‎ | 演算法
 
 
演算法庫
有約束演算法與針對範圍的演算法 (C++20)
有約束的演算法,例如 ranges::copyranges::sort 等……
執行策略 (C++17)
排序及相關操作
劃分操作
排序操作
二分搜尋操作
(於已劃分範圍上)
集合操作(於已排序範圍上)
歸併操作(於已排序範圍上)
堆操作
最小/最大值操作
(C++11)
(C++17)
字典序比較操作
排列操作
C 庫
數值操作
未初始化記憶體上的操作
 
定義於標頭檔案 <algorithm>
template< class InputIt, class UnaryFunc >
UnaryFunc for_each( InputIt first, InputIt last, UnaryFunc f );
(1) (C++20 起為 constexpr)
template< class ExecutionPolicy, class ForwardIt, class UnaryFunc >

void for_each( ExecutionPolicy&& policy,

               ForwardIt first, ForwardIt last, UnaryFunc f );
(2) (C++17 起)

將給定的一元函式物件 f 應用於 [firstlast) 範圍中每個迭代器解引用後的結果。如果 f 返回結果,該結果將被忽略。

1) ffirst 開始按順序應用。

如果 UnaryFunc 不是 可移動構造的 (MoveConstructible),則行為未定義

(C++11 起)
2) f 可能不會按順序應用。該演算法根據 policy 執行。
僅當滿足以下所有條件時,此過載才參與過載決議

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 可以透過解引用迭代器修改範圍的元素。

與其他並行演算法不同,for_each 不允許複製序列中的元素,即使它們是可平凡複製的 (TriviallyCopyable)

目錄

[編輯] 引數

first, last - 迭代器對,定義了要應用函式物件的元素範圍 [firstlast)
policy - 要使用的 執行策略
f - 函式物件,將應用於範圍 [firstlast) 中每個迭代器解引用後的結果

函式的簽名應等效於以下內容

 void fun(const Type &a);

簽名不需要有 const &
型別  Type 必須是使得型別為 InputIt 的物件可以被解引用,然後隱式轉換為  Type

型別要求
-
InputIt 必須滿足 LegacyInputIterator 的要求。
-
ForwardIt 必須滿足 LegacyForwardIterator 的要求。

[編輯] 返回值

1) f
2) (無)

[編輯] 複雜度

精確地 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++ 標準。

缺陷報告 應用於 釋出時的行為 正確的行為
LWG 475 C++98 不清楚 f 是否可以修改
正在迭代的序列元素(for_each
歸類為“非修改序列操作”)
明確(如果
迭代器型別是可變的,則允許)
LWG 2747 C++11 過載 (1) 返回 std::move(f) 返回 f(其隱式移動)

[編輯] 另請參閱

對一個範圍的元素應用函式,並將結果儲存在目標範圍中
(函式模板) [編輯]
對序列中的前 N 個元素應用函式物件
(函式模板) [編輯]
範圍中的元素應用一元函式物件
(演算法函式物件)[編輯]
對序列中的前 N 個元素應用函式物件
(演算法函式物件)[編輯]
range-for 迴圈(C++11) 執行範圍上的迴圈[編輯]