std::accumulate
| 定义于头文件 <numeric>
|
||
template< class InputIt, class T >
T accumulate( InputIt first, InputIt last, T init );
|
(1) | (自 C++20 起为 constexpr) |
template< class InputIt, class T, class BinaryOp >
T accumulate( InputIt first, InputIt last, T init, BinaryOp op );
|
(2) | (自 C++20 起为 constexpr) |
计算给定值 init 与范围 [first, last) 中元素的和。
acc (类型为 T) 使用初始值 init 然后将其修改为 acc = acc + *i(C++20 前)acc = std::move(acc) + *i(C++20 起) 对于每个迭代器 i 在范围 [first, last) 中按顺序。acc (类型为 T) 使用初始值 init 然后将其修改为 acc = op(acc, *i)(C++20 前)acc = op(std::move(acc), *i)(C++20 起) 对于每个迭代器 i 在范围 [first, last) 中按顺序。如果满足以下任一条件,则行为未定义:
T不是 CopyConstructible。T不是 CopyAssignable。op修改了[first,last)中的任何元素。op使[first,last]中的任何迭代器或子范围失效。
参数
| first, last | - | 定义待累加元素 范围 的迭代器对 |
| init | - | 累加的初始值 |
| op | - |
将被应用的二元操作函数对象
函数签名应等价于: Ret fun ( const Type1 & a, const Type2 & b ) ;
签名无需包含
const
&
。
|
| 类型要求 | ||
-
InputIt
必须满足
LegacyInputIterator
的要求。
|
||
返回值
acc 在所有修改之后。
可能的实现
| accumulate (1) |
|---|
template<class InputIt, class T> constexpr // since C++20 T accumulate(InputIt first, InputIt last, T init) { for (; first != last; ++first) init = std::move(init) + *first; // std::move since C++20 return init; } |
| accumulate (2) |
template<class InputIt, class T, class BinaryOperation> constexpr // since C++20 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; } |
注释
std::accumulate
执行的是
左折叠
操作。若要执行右折叠,必须反转二元运算符的参数顺序,并使用反向迭代器。
如果留给类型推断处理, op 会以与 init 相同的类型进行操作,这可能导致迭代器元素发生非预期的类型转换。例如,当 v 的类型为 std:: vector < double > 时, std :: accumulate ( v. begin ( ) , v. end ( ) , 0 ) 很可能不会产生期望的结果。
示例
#include <functional> #include <iostream> #include <numeric> #include <string> #include <vector> int main() { std::vector<int> v{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int sum = std::accumulate(v.begin(), v.end(), 0); int product = std::accumulate(v.begin(), v.end(), 1, std::multiplies<int>()); auto dash_fold = [](std::string a, int b) { return std::move(a) + '-' + std::to_string(b); }; std::string s = std::accumulate(std::next(v.begin()), v.end(), std::to_string(v[0]), // 从第一个元素开始 dash_fold); // 使用反向迭代器进行右折叠 std::string rs = std::accumulate(std::next(v.rbegin()), v.rend(), std::to_string(v.back()), // 从最后一个元素开始 dash_fold); std::cout << "sum: " << sum << '\n' << "product: " << product << '\n' << "dash-separated string: " << s << '\n' << "dash-separated string (right-folded): " << rs << '\n'; }
输出:
sum: 55 product: 3628800 dash-separated string: 1-2-3-4-5-6-7-8-9-10 dash-separated string (right-folded): 10-9-8-7-6-5-4-3-2-1
缺陷报告
下列行为变更缺陷报告被追溯应用于先前发布的C++标准。
| 缺陷报告 | 应用于 | 发布时的行为 | 正确行为 |
|---|---|---|---|
| LWG 242 | C++98 | op 不能有副作用 | 它不能修改所涉及的区间 |
参见
|
计算范围内相邻元素的差值
(函数模板) |
|
|
计算两个元素范围的内积
(函数模板) |
|
|
计算元素范围的部分和
(函数模板) |
|
|
(C++17)
|
类似于
std::accumulate
,但无序执行
(函数模板) |
|
(C++23)
|
对元素范围进行左折叠
(算法函数对象) |