为什么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;
}
如果使用+=
运算符实现,这会不会更有效/更简洁/更好?
答案 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 + *i
或cc = binary_op(acc, *i)
修改它} 范围中i
按顺序排列。
其他数值算法也是如此。
但这就是他们现在实施的原因。但是,要了解原始原因,需要go further down the rabbit hole:
类型要求
对于第一个版本,带有两个参数的版本:
[first,last)
是输入迭代器的模型。InputIterator
是可分配的模型。- 如果
T
是x
类型的对象且T
是y
InputIterator
类型的对象,则value
是定义x + y
的返回类型可转换为x + y
。
那么,为什么呢?让我们问一下STL背后的思想家亚历山大·斯捷潘诺夫:
[A]用户在两天前就StackOverflow问过[问题] 数值算法的实现和制定
T
或accumulate
,inner_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的其余部分使用二进制运算符,而+=
是操作。所以有plus
,multiplies
等,但没有add_action
(比如说)。操作符和操作是完全对称的,但如果您实现了90多种算法,那么在某些时候您可能不得不停止添加新概念并将其发送。
Alex已经表示他从未打算让他的STL成为所有STL开发的终结,尤其是。因为标准化版本只包含他最初提出的一小部分。这是一个明显的扩展。