为什么 std::random_shuffle 方法在 C++14 中被弃用?

问题描述 投票:0回答:5

根据 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

不同的函数减速似乎没有默认参数集。 这背后的原因是什么? 是否添加了某种替代方案?

c++ c++11 deprecated c++14 stl-algorithm
5个回答
53
投票

std::random_shuffle
may 在底层使用
random
C 系列函数。这些函数使用全局状态作为种子和其他状态。

因此它已被弃用,因为

shuffle
会做同样的事情,但更好。也就是说,它使用 C++11 中新的
<random>
标头,该标头不使用全局状态,而是使用生成器、设备和发行版的自己的对象。


48
投票

std::random_shuffle
(有效地)被
std::shuffle
取代。您确实需要传递第三个参数(随机数生成器),但作为交换,您可以获得更好的定义和(通常)行为。

std::random_shuffle
的定义相当模糊。它通常使用
rand()
来生成随机数,但没有说明它是否(以及如何)调用
srand
,因此您不能依赖(例如)
rand
被按照您想要的方式播种(并且如果你播种了它,你就不能依赖它的使用)。如果没记错的话,还有一些令人困惑(并且有些自相矛盾)的语言,可以被解释为说
random_shuffle
根本不能使用
rand
,和/或它不能用
srand 播种它
。即使在最好的情况下,
rand()
的许多实现也相当糟糕,因此即使在最好的情况下,您也不能依赖有用的结果。

底线:

random_shuffle
没有损失。使用
std::shuffle
来代替,你的代码会更好。


16
投票

我们可以在这份文档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()
,但这不会改变基本原理。
    


6
投票
rand()

已被弃用,因为它的 RNG 未指定 - 不仅

you
不必指定它,而且标准本身也没有指定它。例如,在 VC++ 上,它使用 random_shuffle,但实现得非常糟糕!
    


5
投票

rand()

#include <random>
...
std::random_device rd;
std::mt19937 g(rd());
std::shuffle(v.begin(), v.end(), g);

在许多平台上产生非确定性随机数据,并且生成器

rd
使用具有大状态的
Mersenne Twister 伪随机生成器

© www.soinside.com 2019 - 2024. All rights reserved.