Namespaces
Variants

std::accumulate

来自 zh.cppreference.net
 
 
算法库
受约束的算法和范围上的算法 (C++20)
受约束的算法,例如 ranges::copy, ranges::sort, ...
排序和相关操作
划分操作
(C++11)    

排序操作
二分搜索操作
(在划分范围上)
集合操作 (在排序范围上)
合并操作 (在排序范围上)
堆操作
最小/最大操作
(C++11)
(C++17)
字典序比较操作
排列操作


 
 
定义于头文件 <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) 中元素的和。

1) 初始化累加器 acc (类型为 T) 使用初始值 init 然后将其修改为 acc = acc + *i(C++20 前)acc = std::move(acc) + *i(C++20 起) 对于每个迭代器 i 在范围 [first, last) 中按顺序。
2) 初始化累加器 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 & 。
类型 Type1 必须满足: T 类型对象可隐式转换为 Type1 。类型 Type2 必须满足: InputIt 类型对象可解引用后隐式转换为 Type2 。类型 Ret 必须满足: T 类型对象可被赋予 Ret 类型的值。 ​

类型要求
-
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 ,但无序执行
(函数模板)
对元素范围进行左折叠
(算法函数对象)