为什么在C++ 14中不推荐使用std :: shuffle方法?

Tre*_*key 48 c++ deprecated stl-algorithm c++11 c++14

根据std :: shufle上的cppreference.com参考站点,在c ++ 14中不推荐使用以下方法:

template< class RandomIt >
void random_shuffle( RandomIt first, RandomIt last );
Run Code Online (Sandbox Code Playgroud)

为什么我们不再能够在不传递第三个参数的情况下调用以下函数?

std::random_shuffle(v.begin(),v.end()); //no longer valid in c++14
Run Code Online (Sandbox Code Playgroud)

看起来好像不同的功能减速具有默认参数设置.这背后的原因是什么?是否添加了某种替代方案?

Ger*_*ago 47

std::random_shuffle randomC系列功能可以在引擎盖下使用.这些函数使用种子和其他状态的全局状态.

因此它会被弃用,因为它shuffle会做同样的事情,但更好.也就是说,它使用<random>来自C++ 11 的新标头,它不使用全局状态,但它自己的对象使用生成器,设备和分发.

  • `std :: random_shuffle`**可以**使用`rand`.使用`rand`不是*必需*.有些实现有,有些没有. (12认同)

Jer*_*fin 43

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

std::random_shuffle定义相当差.它通常用于rand()生成随机数,但没有说它是否(以及如果是这样)它所调用srand,所以你不能(仅举一个例子)依赖于rand你想要的种子(如果你播种它,你就不能取决于投入使用).如果记忆起作用,还有一些令人困惑的(并且有点自相矛盾)的语言可以被解释为说random_shuffle根本不能使用rand,和/或它不能用它来播种srand.即使充其量,许多实现rand()都很差,所以即使在最好的情况下也不能依赖有用的结果.

底线:random_shuffle没有损失.std::shuffle相反,请使用,您的代码将更好.

  • `random_shuffle`中的`RandomNumberGenerator`与`shuffle`中的`UniformRandomNumberGenerator`具有不同的API.后者的API与[rand.req.urng]中的统一随机数生成器要求一致.前者只有在`random_shuffle`的requires子句中指定的API. (14认同)

Sha*_*our 16

我们可以在本文件N3775中找到理由:贬低兰德和朋友说:

因此,我们现在建议执行该计划的下一步,以阻止使用传统的C函数rand以及其相关的播种函数srand和上限宏RAND_MAX.6特别是,我们建议通过正式弃用来开始这种转变:

  • rand,srand和RAND_MAX和
  • 算法random_shuffle()(然而,保持随机播放).

弃用random_shuffle()的基本原理是指定一个重载以依赖于rand,同时指定另一个重载以便需要来自用户的难以生成的分发对象.这种分布已经是我们保留的洗牌的隐含部分.

后来的文件在C++ 14,v2中劝阻rand()重申了这个立场.

更新

正如Howard Hinnant所说,N3775有一个错误:rand_shuffle()被允许但不需要rand()在引擎盖下使用,但这不会改变原理.

  • N3775错误地指出`rand_shuffle()`被指定为依赖于`rand`.说它被允许在`rand`之上实现是正确的.但它不需要在`rand`之上实现. (2认同)

Cor*_*son 6

random_shuffle因为RNG未指定而被弃用 - 不仅仅是不必指定它,而是标准本身没有指定它.例如,在VC++上,它使用的rand(),实现得非常糟糕!


wco*_*ran 5

其他答案回答了这个问题,但是如果有人正在寻找一些可能适合您需求的剪切粘贴代码,那么以下内容可能会解决问题:

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

rd在许多平台上产生非确定性随机数据,并且生成器g使用具有大状态的Mersenne Twister 伪随机生成器。