std::for_each
定義於標頭檔案 <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, |
(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 可以透過解引用迭代器修改範圍的元素。
與其他並行演算法不同,for_each
不允許複製序列中的元素,即使它們是可平凡複製的 (TriviallyCopyable)。
目錄 |
[編輯] 引數
first, last | - | 迭代器對,定義了要應用函式物件的元素範圍 [ 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++ 標準。
缺陷報告 | 應用於 | 釋出時的行為 | 正確的行為 |
---|---|---|---|
LWG 475 | C++98 | 不清楚 f 是否可以修改 正在迭代的序列元素( for_each 被歸類為“非修改序列操作”) |
明確(如果 迭代器型別是可變的,則允許) |
LWG 2747 | C++11 | 過載 (1) 返回 std::move(f) | 返回 f(其隱式移動) |
[編輯] 另請參閱
對一個範圍的元素應用函式,並將結果儲存在目標範圍中 (函式模板) | |
(C++17) |
對序列中的前 N 個元素應用函式物件 (函式模板) |
(C++20) |
對範圍中的元素應用一元函式物件 (演算法函式物件) |
(C++20) |
對序列中的前 N 個元素應用函式物件 (演算法函式物件) |
range-for 迴圈(C++11) |
執行範圍上的迴圈 |