Namespaces
Variants

std:: partial_sum

From cppreference.net
Algorithm library
Constrained algorithms and algorithms on ranges (C++20)
Constrained algorithms, e.g. ranges::copy , ranges::sort , ...
Execution policies (C++17)
Non-modifying sequence operations
Batch operations
(C++17)
Search operations
Modifying sequence operations
Copy operations
(C++11)
(C++11)
Swap operations
Transformation operations
Generation operations
Removing operations
Order-changing operations
(until C++17) (C++11)
(C++20) (C++20)
Sampling operations
(C++17)

Sorting and related operations
Partitioning operations
Sorting operations
Binary search operations
(on partitioned ranges)
Set operations (on sorted ranges)
Merge operations (on sorted ranges)
Heap operations
Minimum/maximum operations
Lexicographical comparison operations
Permutation operations
C library
Numeric operations
Operations on uninitialized memory
定义于头文件 <numeric>
template < class InputIt, class OutputIt >

OutputIt partial_sum ( InputIt first, InputIt last,

OutputIt d_first ) ;
(1) (自 C++20 起 constexpr)
template < class InputIt, class OutputIt, class BinaryOp >

OutputIt partial_sum ( InputIt first, InputIt last,

OutputIt d_first, BinaryOp op ) ;
(2) (自 C++20 起 constexpr)
1) [ first , last ) 为空范围,则不执行任何操作。
否则,按顺序执行以下操作:
  1. 创建一个累加器 acc ,其类型为 InputIt 值类型 ,并用 * first 初始化。
  2. acc 赋值给 * d_first
  3. 对于区间 [ 1 , std:: distance ( first, last ) ) 内的每个整数 i ,按顺序执行以下操作:
a) 计算 acc + * iter (C++20 前) std :: move ( acc ) + * iter (C++20 起) ,其中 iter first 的第 i 迭代器。
b) 将结果赋值给 acc
c) acc [1] 赋值给 * dest ,其中 dest d_first 的第 i 迭代器。
2) (1) 相同,但改为计算 op ( acc, * iter ) (C++20前) op ( std :: move ( acc ) , * iter ) (C++20起)

给定 binary_op 作为实际二元操作:

  • 若满足以下任一条件,则程序非良构:
  • InputIt 的值类型无法从 * first 构造。
  • 无法将 acc 写入 d_first
  • binary_op ( acc, * iter ) (C++20 前) binary_op ( std :: move ( acc ) , * iter ) (C++20 起) 的结果无法隐式转换为 InputIt 的值类型。
  • 给定 d_last 作为待 返回 的迭代器,若满足以下任一条件,则行为未定义:
  • binary_op 会修改 [ first , last ) [ d_first , d_last ) 中的任意元素。
  • binary_op 会使 [ first , last ] [ d_first , d_last ] 中的任意迭代器或子范围失效。


  1. 实际赋值的值应为前一步赋值操作的结果。此处我们假定赋值结果为 acc

目录

参数

first, last - 定义待求和元素 范围 的迭代器对
d_first - 目标范围的起始位置;可等于 first
op - 将被应用的二元操作函数对象

函数签名应等价于:

Ret fun ( const Type1 & a, const Type2 & b ) ;

签名无需包含 const &
类型 Type1 必须满足: std:: iterator_traits < InputIt > :: value_type 类型的对象能隐式转换为 Type1 。类型 Type2 必须满足: InputIt 类型的对象可解引用并隐式转换为 Type2 。类型 Ret 必须满足: InputIt 类型的对象可解引用并赋以 Ret 类型的值。 ​

类型要求
-
InputIt 必须满足 LegacyInputIterator 的要求。
-
OutputIt 必须满足 LegacyOutputIterator 的要求。

返回值

指向最后被写入元素之后位置的迭代器,若 [ first , last ) 为空范围则返回 d_first

复杂度

给定 N std:: distance ( first, last )

1) 恰好需要 N-1 operator + 运算符的应用。
2) 恰好需要 N-1 次二元函数 op 的应用。

可能的实现

partial_sum (1)
template<class InputIt, class OutputIt>
constexpr // 自 C++20 起
OutputIt partial_sum(InputIt first, InputIt last, OutputIt d_first)
{
    if (first == last)
        return d_first;
    typename std::iterator_traits<InputIt>::value_type sum = *first;
    *d_first = sum;
    while (++first != last)
    {
        sum = std::move(sum) + *first; // 自 C++20 起使用 std::move
        *++d_first = sum;
    }
    return ++d_first;
    // 或自 C++14 起:
    // return std::partial_sum(first, last, d_first, std::plus<>());
}
partial_sum (2)
template<class InputIt, class OutputIt, class BinaryOp>
constexpr // 自 C++20 起
OutputIt partial_sum(InputIt first, InputIt last, 
                     OutputIt d_first, BinaryOp op)
{
    if (first == last)
        return d_first;
    typename std::iterator_traits<InputIt>::value_type acc = *first;
    *d_first = acc;
    while (++first != last)
    {
        acc = op(std::move(acc), *first); // 自 C++20 起使用 std::move
        *++d_first = acc;
    }
    return ++d_first;
}

注释

acc 的引入源于 LWG 问题 539 的决议。之所以使用 acc 而非直接对结果求和(即 * ( d_first + 2 ) = ( * first + * ( first + 1 ) ) + * ( first + 2 ) ; ),是因为当以下类型不匹配时,后者的语义会令人困惑:

  • InputIt 的值类型
  • OutputIt 的可写入类型
  • operator + op 的参数类型
  • operator + op 的返回类型

acc 作为中间对象,用于存储并提供计算每一步的值:

  • 其类型为 InputIt 的值类型
  • 它被写入到 d_first
  • 其值被传递给 operator + op
  • 它存储 operator + op 的返回值
enum not_int { x = 1, y = 2 };
char i_array[4] = {100, 100, 100, 100};
not_int e_array[4] = {x, x, y, y};
int  o_array[4];
// 正确:使用 operator+(char, char) 并将 char 值赋给 int 数组
std::partial_sum(i_array, i_array + 4, o_array);
// 错误:无法将 not_int 值赋给 int 数组
std::partial_sum(e_array, e_array + 4, o_array);
// 正确:在需要时执行类型转换
// 1. 创建 char 类型的 “acc”(值类型)
// 2. char 参数用于 long 乘法运算(char -> long)
// 3. long 类型的乘积被赋给 “acc”(long -> char)
// 4. “acc” 被赋给 “o_array” 的元素(char -> int)
// 5. 返回步骤 2 处理输入范围内剩余元素
std::partial_sum(i_array, i_array + 4, o_array, std::multiplies<long>{});

示例

#include <functional>
#include <iostream>
#include <iterator>
#include <numeric>
#include <vector>
int main()
{
    std::vector<int> v(10, 2); // v = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2}
    std::cout << "前 " << v.size() << " 个偶数为: ";
    // 将结果写入 cout 流
    std::partial_sum(v.cbegin(), v.cend(), 
                     std::ostream_iterator<int>(std::cout, " "));
    std::cout << '\n';
    // 将结果写回向量 v
    std::partial_sum(v.cbegin(), v.cend(),
                     v.begin(), std::multiplies<int>());
    std::cout << "前 " << v.size() << " 个 2 的幂为: ";
    for (int n : v)
        std::cout << n << ' ';
    std::cout << '\n';
}

输出:

前 10 个偶数为: 2 4 6 8 10 12 14 16 18 20 
前 10 个 2 的幂为: 2 4 8 16 32 64 128 256 512 1024

缺陷报告

下列行为变更缺陷报告被追溯应用于先前发布的 C++ 标准。

缺陷报告 适用范围 发布时行为 正确行为
LWG 242 C++98 op 不允许产生副作用 不能修改所涉及的区间
LWG 539 C++98 缺少确保结果求值和赋值
合法所需的类型要求
已添加

参见

计算范围内相邻元素的差值
(函数模板)
对范围内的元素进行累加或折叠
(函数模板)
类似于 std::partial_sum ,在第 i th 次求和时包含第 i th 个输入元素
(函数模板)
类似于 std::partial_sum ,在第 i th 次求和时排除第 i th 个输入元素
(函数模板)