std::partial_sum
| 定义于头文件 <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) |
[first, last) 为空,则不做任何事。- 创建一个累加器
acc,其类型为 的值类型InputIt,并用*first初始化。 - 将
acc赋给*d_first。 - 对于
i中的每个整数[1,std::distance(first, last)),按顺序执行下列运算:
acc + *iter(C++20 前)std::move(acc) + *iter(C++20 起),其中 iter 是 i 的下一个第 个迭代器。firstb)accc)op(acc, *iter)op(std::move(acc), *iter)。设 为实际的二元运算:
binary_op若满足以下任一条件,则程序为病式:
- 的值类型不能从
InputIt构造。*first acc不可写入 。d_first- (直到 C++20)
binary_op(acc, *iter)(C++20 起)binary_op(std::move(acc), *iter)的结果不能隐式转换为InputIt的值类型。
- 的值类型不能从
- 设
d_last为要返回的迭代器,若满足以下任一条件,则行为未定义:
binary_op[first,last)或[d_first,d_last)的任何元素被修改。binary_op[first,last]或[d_first,d_last]中的任何迭代器或子范围失效。
- ↑ 实际要赋的值是上一步赋值的结果。这里我们假定赋值结果为
acc。
参数
| first, last | - | 定义待求和元素 范围 的迭代器对 |
| d_first | - | 目标范围的起始位置;可等于 first |
| op | - |
将被应用的二元操作函数对象
函数签名应等价于: Ret fun ( const Type1 & a, const Type2 & b ) ;
签名无需包含
const
&
。
|
| 类型要求 | ||
-
InputIt
必须满足
LegacyInputIterator
的要求。
|
||
-
OutputIt
必须满足
LegacyOutputIterator
的要求。
|
||
返回值
指向最后被写入元素之后位置的迭代器,若
[
first
,
last
)
为空范围则返回
d_first
。
复杂度
给定 N 为 std:: distance ( first, last ) :
可能的实现
| 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 |
缺少确保结果求值和赋值
合法所需的类型要求 |
已添加 |
参见
|
计算范围内相邻元素的差值
(函数模板) |
|
|
对范围内的元素进行累加或折叠
(函数模板) |
|
|
(C++17)
|
类似于
std::partial_sum
,在第
i
th
次求和时包含第
i
th
个输入元素
(函数模板) |
|
(C++17)
|
类似于
std::partial_sum
,在第
i
th
次求和时排除第
i
th
个输入元素
(函数模板) |