std::accumulate() 算法
- 自 C++20 起
- 直到 C++20
// (1)
template< class InputIt, class T >
constexpr T accumulate( InputIt first, InputIt last, T init );
// (2)
template< class InputIt, class T, class BinaryOperation >
constexpr T accumulate( InputIt first, InputIt last, T init, BinaryOperation op );
// (1)
template< class InputIt, class T >
T accumulate( InputIt first, InputIt last, T init );
// (2)
template< class InputIt, class T, class BinaryOperation >
T accumulate( InputIt first, InputIt last, T init, BinaryOperation op );
计算给定值 init
与范围 [first
; last
) 中元素的和。
使用初始值 init
初始化累加器 acc
(类型为 T
),然后按顺序使用以下方式修改它:
- (1)
acc = acc + *i
(直到 C++20)acc = std::move(acc) + *i
(自 C++20 起) - (2)
acc = op(acc, *i)
(直到 C++20)acc = op(std::move(acc), *i)
(自 C++20 起)
对于范围 [first
; last
) 中的每个迭代器 i
。
如果 op
使任何迭代器(包括尾迭代器)失效或修改了所涉及范围的任何元素,则行为未定义
参数
first last | 要折叠的元素范围。 |
init | 折叠的初始值。 |
op | 将应用的二元操作函数对象。函数的签名应等同于以下内容
|
类型要求
InputIt | LegacyInputIterator |
T | CopyAssignable CopyConstructible |
返回值
所有修改后的 acc
。
复杂度
精确地 last - first
次递增和赋值。
异常
(无)
可能的实现
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]), // start with first element
dash_fold);
// Right fold using reverse iterators
std::string rs = std::accumulate(std::next(v.rbegin()), v.rend(),
std::to_string(v.back()), // start with last element
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