【问题标题】:A possible implementation of std::shufflestd::shuffle 的可能实现
【发布时间】:2021-12-23 22:33:55
【问题描述】:

这是来自https://en.cppreference.com/w/cpp/algorithm/random_shuffle的算法std::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))]);
     }
 }
  • 为什么算法需要对生成器URGB&amp;&amp; g 的转发引用?只要它不使用std::forward&lt;URGB&gt;(g) 将生成器作为左值或右值转发?

  • 为什么 using 声明在循环体内部而不是在循环体外部?将其留在内部(迭代地)会影响性能吗?谢谢!

【问题讨论】:

  • 因为它是由核心人员编写的。这个问题的目标是什么?这不是您阅读的代码

标签: c++ algorithm shuffle forwarding-reference


【解决方案1】:

为什么算法需要对生成器URGB&amp;&amp; 进行转发引用 g?

因为算法不想复制generator,它通过reference,为了能够接受临时右值generator,它需要一个转发参考

只要不使用std::forward&lt;URGB&gt;(g)转发 生成器是左值还是右值?

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

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

这是一个所谓的std::swap two-step,在using std::swap之后紧跟不合格的swap是惯用的。放在循环里面的好处是它的作用域仅限于循环,放在外面可能会污染命名。

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

没有。

【讨论】:

  • std::swap 两步”是什么意思?所以你的意思是:using std::swap; for(;;){ swap(x, y);}for(;;){ using std::swap; swap(x, y);} 不一样?
  • @ItachiUchiwa。他们是一样的。但后者是成语形式。
  • 你能告诉我后者吗?我没听说过。
  • 我知道这个,虽然我不知道它的名字“两步交换”,但你没有明白我的意思。我说:为什么不使用“两步交换”,将 using 声明放在循环体之外:using std::swap; for(){ swap(x, y);} 而不是循环体内部:for(){ using std::swap; swap(x, y);}
  • @ItachiUchiwa。正如我所说,这只是惯用的风格。你也可以把它放在外面。放在for循环里面的好处是它的作用域只在for循环里面,放在for循环外面may pollute the naming
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-03-18
  • 1970-01-01
  • 2018-11-26
  • 2022-10-23
  • 2014-04-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多