为什么std::shuffle方法在c++ 14中被弃用?
Why are std::shuffle methods being deprecated in C++14?
根据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伪随机生成器。
- 使用std::multimap迭代器创建std::list
- C++中std::resize(n)和std::shrink_to_fit之间的区别
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 如何导出包含具有"std::unique_ptr"值的"std::map"属性的
- 从持续时间构造std::chrono::system_clock::time_point
- std::具有相同基类的类的变体
- std::向量与传递值的动态数组
- 使用std::vector的OpenCL矩阵乘法
- std::map<struct,struct>::find 找不到匹配项,但是如果我循环通过 begin() 到 end(),我在那里看到匹配项
- std::condition_variable::wait()如何评估给定的谓词
- 如何获取std::result_of函数的返回类型
- std::原子加载和存储都需要吗
- 将对象移动到std::shared_ptr
- POCO::PostgreSQL:如何将std::vector支持添加到`Binder::bind`
- 使用一个考虑到std::map中键值的滚动或换行的键
- 如何从 std::atomic 中提取指针 T<T>?
- 为什么 std::unique 不调用 std::sort?
- 使用std::函数映射对象方法
- 可组合的lambda/std::函数与std::可选