std::min的实现方式

5

std::min函数的实现在cppreference原始STL中都是这样的:

return (b < a) ? b : a;

但我认为这个版本更易读:

return (a < b) ? a : b;

让我想知道:这两种实现是否等效?为什么实现方式是这样的?

2
我不知道这个实现背后的理由,但两者应该产生相同的输出,我认为这只是一个风格问题。 - legends2k
2
在实现 max 函数时是否有某种对称性?即强调比较中的翻转而不是返回值中的翻转。 - BoBTFish
1
请正确实现min函数。相关内容请参考:https://dev59.com/-m855IYBdhLWcg3wvW_d - Nate Kohl
1
它们不是等价的:http://ideone.com/ej7TIA。如果 std::min 允许两种不同类型,它们的返回类型也会不同(一个将是 decltype(b),另一个将是 decltype(a))。 - Yakk - Adam Nevraumont
9
请注意,标准保证 minmax 函数会在 c++11initializer_list 版本中返回“当参数相等时返回第一个参数”或“当多个参数等于最小值时返回最左边的参数的副本”。(25.4.7) - BoBTFish
显示剩余8条评论
3个回答

6

如果两种不同的实现在相等时选择第一个还是第二个对象作为最小值,则可能会对对象产生影响,但对于基本类型来说则没有区别。

这与其他算法的实现结合起来可能会产生更大的影响。例如,如果排序算法使用min(a[i], a[j]),其中i < ja[i]a[j]具有相同的值,则第一种实现将导致元素之间没有交换,而第二种实现则会进行交换,使排序不稳定。


注意:正如 BoBTFish所提到的那样,C++11标准保证min和max都返回最左边的最小值:

25.4.7:

3 备注:当参数相等时返回第一个参数

6 备注:当多个参数等于最小值时,返回最左边的参数的副本


这两个实现不同,请参见@ChrisCM下面的帖子--(b < a)!=(a > b) - Ben Brammer
2
@BenBrammer,是的,这就是为什么我在你的评论之前4分钟删除了我的答案的原因。 - Shahbaz
@Shabaz,抱歉,我反应有点慢。我的错。 - Ben Brammer
@Shabaz:取消了你的负评,但是你不会得到我的赞,因为你基本上是为了声望而劫持了我的答案,在最初完全搞错之后:P - MobA11y
@ChrisCM,实际上我是从这里劫持的:https://dev59.com/-m855IYBdhLWcg3wvW_d#4174519 - Shahbaz
@ChrisCM,无论如何,这个评论是该问题的最终答案。 - Shahbaz

5
实现并不相同。如果a和b相等,任何一种实现会发生什么?一个将返回对a的引用,另一个将返回对b的引用。当然,这些值是相同的。但考虑一个结构体,其中比较函数只关心一个值,而其他一些值是不同的。这可能会对试图保证稳定排序的排序函数产生重大影响。
最终这是一种风格选择,在相等的情况下我们应该返回第一个还是第二个参数?然而,既然做出了这种风格选择,保持其不变非常重要,这就是为什么会存在像标准定义之类的东西的原因!

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf

搜索"25.4.7"以了解最大值和最小值。


但如何纠正它呢? - thefourtheye
不要搞乱min函数的实现。 - MobA11y
2
@thefourtheye,有什么需要纠正的吗?谁说有什么问题了? - Shahbaz
4
更准确地说,规范已经说明在相等的情况下左边会被返回。因此,在实现中这不是一种样式选择(尽管在标准中可能是一种样式选择,但重复问题的顶部答案和Shahbaz的答案都表明它不是)。 - Christian Rau
我会保留我的答案,以便提供C++标准文档的链接,但你应该接受Ben的答案,并采纳Shahbaz的修改建议。 - MobA11y
显示剩余2条评论

-2

--INCORRECT ANSWER--请查看评论--bb

就我个人的观察而言,STL并不是为了特别易于阅读而编写的,但它非常简洁美观;在这种情况下,要获得相同的结果,唯一可能的另一种方法是

return (a <= b) ? a : b;

这将会是一个更多的字符,并且,在我看来,实际上不太容易阅读。此外,请参见@Shahbaz关于排序稳定性的评论--像min这样的操作对于包含和排除具有明确定义的行为。

简而言之,因为“小于”不等同于“小于或等于”

请参见下面的评论--这个答案在C中作为宏是正确的,但是由于下面评论中解释的原因,在C++中实际上是不正确的。我将其标记为不正确,但保留它,因为评论对于理解很重要和有用。如果我让任何人感到困惑,我深表歉意。


1
此外,标准库更喜欢使用 <== 而不是 <=,可能是为了更容易地重载运算符。 - Yakk - Adam Nevraumont
1
"FWIW" - 没有多少价值。 "因为“小于”不等于“小于或等于”" - 实际上,“小于或等于”甚至不同于“小于”“等于”。这就是为什么您提出的“其他可能的方法”甚至不可能,因为所有标准库的排序功能都依赖于严格的弱排序。 <=不仅仅是一个字符,它是一个完全不同的运算符,与<== 完全无关 - Christian Rau
1
@Yakk 不仅是为了让它更简单,而且为了在运算符重载的情况下能够正常工作,因为 <=< || == 没有任何关系。 - Christian Rau
@Shahbaz,为什么你没有在自己的答案中添加标准引用,而是添加到了一个完全不同的答案中? - Christian Rau
@ChristianRau,啊对了。两个“B”让我有点困惑。既然Bob没有写答案,那我就把它移到我的答案里吧。 - Shahbaz
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接