根据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伪随机生成器。