我认为,由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?