为什么STL数值算法使用'op'而不是'op ='?

时间:2015-03-04 19:17:09

标签: c++ stl

为什么std::numeric算法似乎更喜欢 op 而不是 op = ?例如,以下是LLVM中std::accumulate的实现:

template <class _InputIterator, class _Tp>
inline _LIBCPP_INLINE_VISIBILITY
_Tp
accumulate(_InputIterator __first, _InputIterator __last, _Tp __init)
{
    for (; __first != __last; ++__first)
        __init = __init + *__first;
    return __init;
}

如果使用+=运算符实现,这会不会更有效/更简洁/更好?

5 个答案:

答案 0 :(得分:15)

在标准......

中定义如下

标准是根据+定义的,而不是+=

  

26.7.2累积[accumulate]

template <class InputIterator, class T>
  T accumulate(InputIterator first, InputIterator last, T init);
template <class InputIterator, class T, class BinaryOperation>
  T accumulate(InputIterator first, InputIterator last, T init,
               BinaryOperation binary_op);
     

效果:通过使用初始值acc初始化累加器init来计算其结果,然后为每个迭代器{{1}使用acc = acc + *icc = binary_op(acc, *i)修改它} 范围中   i按顺序排列。

其他数值算法也是如此。

......标准基于STL ......

但这就是他们现在实施的原因。但是,要了解原始原因,需要go further down the rabbit hole

  

类型要求

     

对于第一个版本,带有两个参数的版本:

     
      
  • [first,last)是输入迭代器的模型。
  •   
  • InputIterator是可分配的模型。
  •   
  • 如果Tx类型的对象且Ty InputIterator类型的对象,则value是定义
  •   
  • x + y的返回类型可转换为x + y
  •   

...并且STL已由......创建?

那么,为什么呢?让我们问一下STL背后的思想家亚历山大·斯捷潘诺夫:

  

[A]用户在两天前就StackOverflow问过[问题]   数值算法的实现和制定   Taccumulateinner_product+,按+=定义   而不是reduce(ISO C ++ 11中的第26.7节)。

     

我试图找到决定背后的理由,但即便如此   SGI页面上的版本没有提及任何相关内容   特别选择运营商。

     

仅选择运算符(a = a + b而不是+ = b)   根据您的个人喜好,正如一些评论所假设的那样?是+ b   当时编写操作的更自然的方式是什么?或者是它   只是a = a + b和a = bin_op(a,b)之间的对称问题?

     

- [Zeta]

现在,在你阅读他的答案之前,请记住他大约30年前开始写一个通用的图书馆,他和孟利的初始文件The Standard Template Library将于今年10月成立二十周年。不用多说,我提出他的答案:

  

我怀疑这是a = a + b和a = bin_op(a,b)之间的对称问题,但我真的不记得了。我应该写一份理由文件,说明STL中不同设计选择之间的所有推理,但我没有。遗憾。

(如果斯捷潘诺夫有任何机会读到这篇文章:再次感谢你的回答!)

个人相信Common Lisp a+=b的灵感是另一个因素,但这只是猜测。

从中可以学到什么?

有时,标准中的决定是基于个人偏好和优雅。例如,如果Stroustrup写了STL,他就会“非常喜欢使用+ = b作为更直接的意图表达,通常比a = a + b更快”。但是,我必须承认a = a + b和a = bin_op(a,b)之间的对称性有其自身的美感。

话虽如此,这场a=a+b和{{1}}争议将会带来挑战:

  

当我们定义标准概念时,这个问题将变得非常重要,我不知道如何解决它。 [Stroustrup的;也感谢他回答我的问题!]

就是这样,我希望你能享受到C ++历史的一点点。

答案 1 :(得分:10)

它可能更有效率,而且显然不那么冗长。

以这种方式做事的通常原因是最小化对基础类型的要求。如果您使用+=,则基础类型必须支持+=。对于像int那样微不足道且已经存在的东西,但对于您定义的类,完全有可能定义+=,而不是化合物+=(其中)例如,使用+=的代码显然会失败。)

答案 2 :(得分:1)

在我看来,主要原因是您可以使用标准功能对象std::plus并获得与operator +相同的结果,与使用operator <和标准功能对象{{ 1}}在排序算法,如std::less

答案 3 :(得分:0)

使用+代替+ =。

有很多理由

一个。因为这是正确的方法。 Accumulate is fold,一个在+上运行的函子(将函数映射到函数的函数),而不是+ =。为什么+而不是+ =?因为+ =不是数学函数。

B中。它更有效(在现代编译器上,在所有原始类型和精心设计的对象上)。 + = 30年​​前编译器可能会更快,但现在+更快,除非你积累的是一个具有太多OO的怪异对象。对象生命周期分析在const对象而不是引用上更容易完成。

℃。它更清楚。这个原因与(A)没有实质性的不同。 +比+ =更清晰。清晰度胜过冗长。

答案 4 :(得分:0)

我想,事实是重复使用。 STL的其余部分使用二进制运算符,而+=操作。所以有plusmultiplies等,但没有add_action(比如说​​)。操作符和操作是完全对称的,但如果您实现了90多种算法,那么在某些时候您可能不得不停止添加新概念并将其发送。

Alex已经表示他从未打算让他的STL成为所有STL开发的终结,尤其是。因为标准化版本只包含他最初提出的一小部分。这是一个明显的扩展。