为什么C ++ 11个的随机分布可变的?(Why are c++11 random distribu

2019-08-31 06:01发布

我认为,由C ++ 11随机分布(生成的值uniform_int_distribution ,例如),仅取决于发电机的,其被传递到状态operator() 然而,由于某种原因,没有const中的签名符operator() 这是什么意思,我应该如何通过分布作为函数参数? 我以为我已经把它作为任何非相互参数:通过const引用,但现在我不知道。

Answer 1:

我误解了这个问题,在第一,但是,现在我明白了,这是一个很好的问题。 一些挖掘到的执行的源<random>下g ++给出以下(具有几个比特排除在外,为了清楚起见):

template<typename _IntType = int>
  class uniform_int_distribution
  {

  struct param_type
  {
    typedef uniform_int_distribution<_IntType> distribution_type;

    explicit
    param_type(_IntType __a = 0,
       _IntType __b = std::numeric_limits<_IntType>::max())
    : _M_a(__a), _M_b(__b)
    {
      _GLIBCXX_DEBUG_ASSERT(_M_a <= _M_b);
    }

     private:
    _IntType _M_a;
    _IntType _M_b;
};

public:
  /**
   * @brief Constructs a uniform distribution object.
   */
  explicit
  uniform_int_distribution(_IntType __a = 0,
           _IntType __b = std::numeric_limits<_IntType>::max())
  : _M_param(__a, __b)
  { }

  explicit
  uniform_int_distribution(const param_type& __p)
  : _M_param(__p)
  { }

  template<typename _UniformRandomNumberGenerator>
result_type
operator()(_UniformRandomNumberGenerator& __urng)
    { return this->operator()(__urng, this->param()); }

  template<typename _UniformRandomNumberGenerator>
result_type
operator()(_UniformRandomNumberGenerator& __urng,
       const param_type& __p);

  param_type _M_param;
};

如果我们眯过去所有的_ ,我们可以看到,它只有一个成员参数, param_type _M_param ,这本身就是一个嵌套的结构保持2个积分值-实际上,一个范围。 operator()只在这里声明,没有定义。 一些更多的挖掘给我们带来了定义。 代替张贴在这里所有的代码,这是非常丑陋的(和相当长的),就足以说,没有什么是这个函数内部发生突变。 事实上,增加const的定义和声明将愉快地编译。

接下来的问题是,这是真的每隔分配? 答案是不。 如果我们看一下,为实施std::normal_distribution ,我们发现:

template<typename _RealType>
template<typename _UniformRandomNumberGenerator>
  typename normal_distribution<_RealType>::result_type
  normal_distribution<_RealType>::
  operator()(_UniformRandomNumberGenerator& __urng,
     const param_type& __param)
  {
result_type __ret;
__detail::_Adaptor<_UniformRandomNumberGenerator, result_type>
  __aurng(__urng);

    //Mutation!
if (_M_saved_available)
  {
    _M_saved_available = false;
    __ret = _M_saved;
  }
    //Mutation!

这一切都只是理论化,但我想它不局限于原因const是允许在需要实施者变异的实施。 此外,它使一个更加统一的界面-如果某些operator()const ,有些是非const ,这一切都变得有点凌乱。

然而,他们为什么不干脆让他们常量,让实施者利用mutable我不知道。 有可能的,除非有人在这里曾参与标准化工作的这一部分,你可能不会得到一个很好的答案。

编辑:作为MattieuM指出的, mutable ,多线程不会很好地一起玩。

正如minorly有趣之外, std::normal_distribution产生一次两个值,一个高速缓存(因此_M_saved )。 该operator<<这实际上定义了可以让你在下次调用之前看到这个值operator()

#include <random>
#include <iostream>
#include <chrono>

std::default_random_engine eng(std::chrono::system_clock::now().time_since_epoch().count());
std::normal_distribution<> d(0, 1);

int main()
{
   auto k = d(eng);
   std::cout << k << "\n";
   std::cout << d << "\n";
   std::cout << d(eng) << "\n";
}

这里,输出格式是mu sigma nextval



文章来源: Why are c++11 random distributions mutable?
标签: c++ random c++11