【问题标题】:Why are std::shuffle methods being deprecated in C++14?为什么在 C++14 中不推荐使用 std::shuffle 方法?
【发布时间】:2014-05-01 06:15:18
【问题描述】:

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


    【解决方案1】:

    std::random_shuffle 可以在后台使用random C 系列函数。这些函数将全局状态用于种子和其他状态。

    所以它被弃用了,因为shuffle 会做同样的事情,但更好。也就是说,它使用来自 C++11 的新 &lt;random&gt; 标头,它不使用全局状态,而是使用生成器、设备和分发的自己的对象。

    【讨论】:

    • std::random_shuffle 可以使用rand。使用rand 不是必需。有些实现可以,有些不可以。
    • 感谢指正,我错了。对此不准确深表歉意。
    【解决方案2】:

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

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

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

    【讨论】:

    • 似乎有第二个重载可以接受一个 RNG... 可以使用吗?
    • @Mehrdad:我相信是的。它基本上相当于std::shuffle。不过,我认为没有任何真正的理由比std::shuffle 更喜欢它。
    • random_shuffle 中的 RandomNumberGeneratorshuffle 中的 UniformRandomNumberGenerator 具有不同的 API。后者的 API 与 [rand.req.urng] 中的统一随机数生成器要求一致。前者的 API 仅在 random_shuffle 的 requires 子句中指定。
    【解决方案3】:

    我们可以在这份文件N3775: Deprecating rand and Friends 中找到理由:

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

    • rand、srand 和 RAND_MAX 和
    • 算法 random_shuffle()(但保持随机播放)。

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

    以及后来重申这一立场的文件Discouraging rand() in C++14, v2

    更新

    正如 Howard Hinnant 所指出的,N3775 有一个错误:rand_shuffle() 是允许的,但不需要在后台使用 rand(),但这不会改变基本原理。

    【讨论】:

    • N3775 说 rand_shuffle() 被指定为依赖于 rand 是错误的。可以说允许在rand之上实现是对的。但不需要在rand之上实现。
    • @HowardHinnant 感谢您指出这一点,我想知道为什么 cppreference 使用该措辞,我应该自己在标准中查找它。
    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

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

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

      rd 在许多平台上产生不确定的随机数据,生成器g 使用具有大状态的Mersenne Twister pseudo-random generator

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-04-11
        • 1970-01-01
        • 2019-10-02
        • 2020-04-01
        相关资源
        最近更新 更多