为什么std::shuffle方法在c++ 14中被弃用?

Why are std::shuffle methods being deprecated in C++14?

本文关键字:c++ std shuffle 方法 为什么      更新时间:2023-10-16

根据cppreference.com关于std:: shfle的参考站点,以下方法在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 可以在底层使用random C族函数。这些函数使用全局状态作为种子和其他状态。

所以它被弃用,因为shuffle将做同样的,但更好。也就是说,它使用新的<random>头从c++ 11不使用全局状态,但自己的对象利用生成器,设备和分布。

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

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

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

我们可以在N3775: Deprecating rand and Friends中找到基本原理,其中说:

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

开始此转换:
  • rand、srand和RAND_MAX和
  • 算法random_shuffle()(但是保持shuffle)。

弃用random_shuffle()的理由是指定了一个重载以便依赖在rand上,而另一个重载是指定的,因此需要一个难以生成的分布对象从用户;这样的分布已经是shuffle的隐式部分,我们保留了它。

和后来的c++ 14, v2中的劝阻rand()重申了这一立场。

更新

Howard Hinnant注意到N3775有一个错误:rand_shuffle()被允许但不需要在引擎盖下使用rand(),但这不会改变基本原理。

random_shuffle被弃用是因为它的RNG未指定——不仅不需要指定它,而且标准本身也没有指定它。例如,在vc++中,它使用rand(),它的实现非常糟糕!

其他回答回答了这个问题,但是如果有人正在寻找一些适合您需要的剪切-粘贴代码,下面的代码可能会奏效:

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

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