for_each函數
for_each函數定義在<algorithm>
頭文件中,其函數聲明爲:
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
}
接收兩個迭代器first,last,並對[first,last)範圍內的元素遍歷,傳遞給函數或函數對象f,遍歷結束返回函數或函數對象f
f可以是一個函數,一個函數對象,或者是一個lambda表達式
用函數作爲謂詞
void print(const int &a) {
cout << a << " ";
}
int main() {
std::vector<int> nums{3, 4, 2, 8, 15, 267};
// for_each函數遍歷完之後,會把謂詞返回
void (*pfunc)(const int &) = for_each(nums.begin(), nums.end(), print);
cout << endl;
pfunc(6);
}
用函數對象作爲謂詞
只要是重載了()
運算符的類或者結構體,就是函數對象類,該類的實例即爲函數對象。
結構體中成員屬性和成員方法默認爲public
類中成員屬性和成員方法默認爲private
struct Sum {
Sum() : sum{0} {}
// 重載()運算符
void operator()(int n) { sum += n; }
int sum;
};
std::vector<int> nums{3, 4, 2, 8, 15, 267};
//將容器中的元素遍歷分別傳遞給函數對象進行累加,遍歷結束返回該函數對象
Sum s = std::for_each(nums.begin(), nums.end(), Sum());
//從函數對象中獲取累加結果
std::cout << "sum: " << s.sum << '\n';
用lambda表達式作爲謂詞
std::vector<int> nums{3, 4, 2, 8, 15, 267};
void (*pfunc)(const int &) = for_each(nums.begin(), nums.end(), [](const int &n) { cout << n << " "; });
cout << endl;
pfunc(7);
accumulate函數
accumulate函數定義在numeric
頭文件中,其函數定義有兩種:
第一種實現就是累加[first,last)範圍內的元素,init+=*first
並返回累加結果
template<class InputIt, class T>
T accumulate(InputIt first, InputIt last, T init)
{
for (; first != last; ++first) {
init = std::move(init) + *first; // std::move since C++20
}
return init;
}
第二種實現累加規則不一樣了,累加規則可以在謂詞裏面定義,init = op(std::move(init), *first)
並返回累加結果
template<class InputIt, class T, class BinaryOperation>
T accumulate(InputIt first, InputIt last, T init,
BinaryOperation op)
{
for (; first != last; ++first) {
init = op(std::move(init), *first); // std::move since C++20
}
return init;
}
用函數作爲謂詞
// 注意lhs和rhs的順序!!!
int op_sum(int total, int value) {
return total + value * value;
}
vector<int> v{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for_each(v.begin(), v.end(), [](const int &n) { cout << n << " "; });
// 使用默認累加
cout << accumulate(v.begin(), v.end(), 0) << endl;
// 使用函數作爲謂詞,計算平方和
cout << accumulate(v.begin(), v.end(), 0, op_sum) << endl;
用函數對象作爲謂詞
template<typename T>
class OpSum {
private:
int power;
public:
explicit OpSum(int p) : power(p) {}
T operator()(const T &total, const T &value) { //計算 value的power次方,加到total上
return total + pow(value, power);
}
};
vector<int> v{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for_each(v.begin(), v.end(), [](const int &n) { cout << n << " "; });
// 使用默認累加
cout << accumulate(v.begin(), v.end(), 0) << endl;
// 使用函數對象作爲謂詞,計算平方和
cout << accumulate(v.begin(), v.end(), 0, OpSum<int>(2)) << endl;
用lambda表達式作爲謂詞
vector<int> v{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for_each(v.begin(), v.end(), [](const int &n) { cout << n << " "; });
// 使用默認累加
cout << accumulate(v.begin(), v.end(), 0) << endl;
// 使用lambda作爲謂詞,計算平方和
cout << accumulate(v.begin(), v.end(), 0, [](const int &total, const int &value) { return total + value * value; })
<< endl;
對於一些簡單的需求,我們可以用默認累加或者lambda表達式一行搞定,當然,如果需要更加複雜的需求,比如累加規則多樣,甚至想對不同的數據類型累加規則,那麼推薦使用函數對象。
全部代碼如下:
//函數對象
#include <iostream>
#include <vector>
#include <numeric> //accumulate 在此頭文件定義
#include <algorithm>
#include <cmath>
using namespace std;
// 注意lhs和rhs的順序!!!
int op_sum(int total, int value) {
return total + value * value;
}
template<typename T>
class OpSum {
private:
int power;
public:
explicit OpSum(int p) : power(p) {}
T operator()(const T &total, const T &value) { //計算 value的power次方,加到total上
return total + pow(value, power);
}
};
int main() {
vector<int> v{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for_each(v.begin(), v.end(), [](const int &n) { cout << n << " "; });
// 使用默認累加
cout << accumulate(v.begin(), v.end(), 0) << endl;
// 使用函數作爲謂詞,計算平方和
cout << accumulate(v.begin(), v.end(), 0, op_sum) << endl;
// 使用函數對象作爲謂詞,計算平方和
cout << accumulate(v.begin(), v.end(), 0, OpSum<int>(2)) << endl;
// 使用lambda作爲謂詞,計算平方和
cout << accumulate(v.begin(), v.end(), 0, [](const int &total, const int &value) { return total + value * value; })
<< endl;
return 0;
}
對比
for_each | accumulate | |
---|---|---|
謂詞 | 僅需一個參數,對參數的處理不需要和[first,last)範圍內的其它元素有關聯 | 需要兩個參數(init,value),對範圍內的元素處理有關聯 |
返回結果 | 將謂詞返回,謂詞中可以存放處理的結果 | 將累加結果返回 |
總結 | 對範圍內的元素進行某種變換調整 | 常用於累加計算範圍內的元素的映射 |