首页 > 解决方案 > std::shuffle 的可能实现

问题描述

这是std::shuffle来自https://en.cppreference.com/w/cpp/algorithm/random_shuffle的算法:

 template<class RandomIt, class URBG>
 void shuffle(RandomIt first, RandomIt last, URBG&& g)
 {
     typedef typename std::iterator_traits<RandomIt>::difference_type diff_t;
     typedef std::uniform_int_distribution<diff_t> distr_t;
     typedef typename distr_t::param_type param_t;

     distr_t D;
     diff_t n = last - first;
     for (diff_t i = n-1; i > 0; --i) {
         using std::swap;
         swap(first[i], first[D(g, param_t(0, i))]);
     }
 }

标签: c++algorithmshuffleforwarding-reference

解决方案


为什么算法需要对生成器的转发引用URGB&& g

因为算法不想复制generator,它通过引用传递,并且为了能够接受临时右值generator,它需要一个转发引用

只要它不用于std::forward<URGB>(g)将生成器作为左值或右值转发?

因为generator不仅仅被调用一次。如果右值被转发,它的状态可能会在下一次调用之前改变。

为什么 using 声明在循环体内部而不是在循环体外部?

这就是所谓std::swap的两步swap在 之后立即使用 unqualified 是惯用的using std::swap。放在循环里面的好处是它的作用域仅限于循环,放在外面可能会污染命名。

将其留在内部(迭代地)会影响性能吗?

不。


推荐阅读