跳到主要内容

std::accumulate() 算法

// (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 );

计算给定值 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

将应用的二元操作函数对象。函数的签名应等同于以下内容

Ret fun(const Type1 &a, const Type2 &b);
  • 签名不需要包含 const&
  • Type1 类型必须是 T 类型的对象可以隐式转换为它的类型。
  • Type2 类型必须是 InputIt 类型的对象可以解引用并随后隐式转换为它的类型。
  • Ret 类型必须是 T 类型的对象可以赋值为其类型的值。

类型要求

InputItLegacyInputIterator
TCopyAssignable
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) 可能不会给出期望的结果。

示例

Main.cpp
#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
本文源自 此 CppReference 页面。它可能为了改进或编辑偏好而被修改。点击“编辑此页面”查看本文档的所有更改。
悬停查看原始许可证。

std::accumulate() 算法

// (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 );

计算给定值 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

将应用的二元操作函数对象。函数的签名应等同于以下内容

Ret fun(const Type1 &a, const Type2 &b);
  • 签名不需要包含 const&
  • Type1 类型必须是 T 类型的对象可以隐式转换为它的类型。
  • Type2 类型必须是 InputIt 类型的对象可以解引用并随后隐式转换为它的类型。
  • Ret 类型必须是 T 类型的对象可以赋值为其类型的值。

类型要求

InputItLegacyInputIterator
TCopyAssignable
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) 可能不会给出期望的结果。

示例

Main.cpp
#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
本文源自 此 CppReference 页面。它可能为了改进或编辑偏好而被修改。点击“编辑此页面”查看本文档的所有更改。
悬停查看原始许可证。