我认为c ++ 11随机分布(uniform_int_distribution例如)生成的值仅取决于传递给它的生成器的状态operator().但是,由于某些原因const,签名中没有说明符operator().这是什么意思,我应该如何将分布作为函数参数传递?我认为我必须将它作为任何非相互参数传递:通过const引用,但现在我不确定.
Yuu*_*shi 22
我起初误解了这个问题,然而,现在我明白了,这是一个很好的问题.一些深入研究<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;
};
Run Code Online (Sandbox Code Playgroud)
如果我们斜视所有的_,我们可以看到它只有一个成员参数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!
Run Code Online (Sandbox Code Playgroud)
这只是理论化,但我想它不受限制的原因const是允许实现者在需要时改变它们的实现.此外,它保持一个更统一的界面 - 如果有些operator()是非const,有些是非const,它都变得有点混乱.
但是,为什么他们不是简单地让它们成为常量而让实施者利用mutable我不确定.可能,除非这里的某个人参与了标准化工作的这一部分,否则你可能无法得到一个好的答案.
编辑:正如MattieuM指出的那样,mutable多个线程不能很好地协同工作.
就像一个小问题一样,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";
}
Run Code Online (Sandbox Code Playgroud)
这里,输出格式是mu sigma nextval.
| 归档时间: |
|
| 查看次数: |
2035 次 |
| 最近记录: |