了解std :: accumulate [英] Understanding std::accumulate

查看:216
本文介绍了了解std :: accumulate的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道为什么需要 std :: accumulate (又称为reduce)第3个参数。对于那些不知道累积是什么的人,它的用法如下:

I want to know why std::accumulate (aka reduce) 3rd parameter is needed. For those who do not know what accumulate is, it's used like so:

vector<int> V{1,2,3};  
int sum = accumulate(V.begin(), V.end(), 0);
// sum == 6

调用累积等效于:

sum = 0;  // 0 - value of 3rd param
for (auto x : V)  sum += x;

还有可选的第4个参数,该参数允许用任何其他操作替换加法。

There is also optional 4th parameter, which allow to replace addition with any other operation.

我听说过,如果您需要说不累加而是乘以向量的元素,则需要其他(非零)初始值:

Rationale that I've heard is that if you need let say not to add up, but multiply elements of a vector, we need other (non-zero) initial value:

vector<int> V{1,2,3};
int product = accumulate(V.begin(), V.end(), 1, multiplies<int>());

但是为什么不喜欢Python-设置 V.begin( ),使用范围从 V.begin()+ 1 开始。像这样的东西:

But why not do like Python - set initial value for V.begin(), and use range starting from V.begin()+1. Something like this:

int sum = accumulate(V.begin()+1, V.end(), V.begin());

这将适用于任何操作。为什么根本需要第三个参数?

This will work for any op. Why is 3rd parameter needed at all?

推荐答案

事情的发展,令人讨厌的代码肯定知道范围是不能为空,并且要从范围的第一个元素开始累积。

The way things are, it is annoying for code that knows for sure a range isn't empty and that wants to start accumulating from the first element of the range on. Depending on the operation that is used to accumulate with, it's not always obvious what the 'zero' value to use is.

另一方面,如果您仅提供一个版本,则取决于用于进行累加的操作,并不总是很明显。需要非空范围,对于不确定不确定其范围是否为空的调用者来说很烦人。

If on the other hand you only provide a version that requires non-empty ranges, it's annoying for callers that don't know for sure that their ranges aren't empty. An additional burden is put on them.

一个观点是,两者兼而有之的当然是同时提供了两种功能。例如,Haskell同时提供 foldl1 foldr1 (需要非空列表)以及 foldl folder (反映了 std :: transform )。

One perspective is that the best of both worlds is of course to provide both functionality. As an example, Haskell provides both foldl1 and foldr1 (which require non-empty lists) alongside foldl and foldr (which mirror std::transform).

另一个观点是,由于可以通过简单的转换就另一个实现(如您所展示的: std :: transform(std: :next(b),e,* b,f)- std :: next 是C ++ 11,但要点仍然成立) ,则最好使接口尽可能地小,而不会真正丧失表达能力。

Another perspective is that since the one can be implemented in terms of the other with a trivial transformation (as you've demonstrated: std::transform(std::next(b), e, *b, f) -- std::next is C++11 but the point still stands), it is preferable to make the interface as minimal as it can be with no real loss of expressive power.

这篇关于了解std :: accumulate的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆