根据 std::shufle 上的 cppreference.com 参考站点,以下方法在 c++14 中已被弃用:
template< class RandomIt >
void random_shuffle( RandomIt first, RandomIt last );
为什么我们将无法在不传递第三个参数的情况下调用以下函数?
std::random_shuffle(v.begin(),v.end()); //no longer valid in c++14
不同的函数减速似乎没有默认参数集。 这背后的原因是什么? 是否添加了某种替代方案?
std::random_shuffle
may 在底层使用 random
C 系列函数。这些函数使用全局状态作为种子和其他状态。
因此它已被弃用,因为
shuffle
会做同样的事情,但更好。也就是说,它使用 C++11 中新的 <random>
标头,该标头不使用全局状态,而是使用生成器、设备和发行版的自己的对象。
std::random_shuffle
(有效地)被 std::shuffle
取代。您确实需要传递第三个参数(随机数生成器),但作为交换,您可以获得更好的定义和(通常)行为。
std::random_shuffle
的定义相当模糊。它通常使用 rand()
来生成随机数,但没有说明它是否(以及如何)调用 srand
,因此您不能依赖(例如)rand
被按照您想要的方式播种(并且如果你播种了它,你就不能依赖它的使用)。如果没记错的话,还有一些令人困惑(并且有些自相矛盾)的语言,可以被解释为说 random_shuffle
根本不能使用 rand
,和/或它不能用 srand
播种它
。即使在最好的情况下,rand()
的许多实现也相当糟糕,因此即使在最好的情况下,您也不能依赖有用的结果。
底线:
random_shuffle
没有损失。使用 std::shuffle
来代替,你的代码会更好。
我们可以在这份文档N3775:弃用兰特和朋友中找到其基本原理,其中写道:
因此,我们现在建议执行该计划的下一步,以阻止使用 传统 C 函数 rand 及其关联的种子函数 srand 和上限宏 RAND_MAX。6 特别是,我们建议通过正式弃用来开始此转换:
- rand、srand 和 RAND_MAX 以及
- 算法 random_shuffle() (但是保持随机播放)。
弃用 random_shuffle() 的理由是指定一个重载以依赖于 在 rand 上,而指定其他重载以便需要难以生成的分布 来自用户的对象;这样的分布已经是 shuffle 的隐含部分,我们保留它。
以及后来的文档 C++14 v2 中的不鼓励 rand() 重申了这一立场。
更新
正如 Howard Hinnant 指出的那样,
N3775
有一个错误:允许但不要求在幕后使用 rand_shuffle()
,但这不会改变基本原理。rand()
已被弃用,因为它的 RNG 未指定 - 不仅
you不必指定它,而且标准本身也没有指定它。例如,在 VC++ 上,它使用
random_shuffle
,但实现得非常糟糕!