gpt4 book ai didi

c++ - 为什么 c++11 随机分布是可变的?

转载 作者:IT老高 更新时间:2023-10-28 12:33:48 25 4
gpt4 key购买 nike

我认为 c++11 随机分布(例如 uniform_int_distribution)生成的值仅取决于传递给 operator() 的生成器的状态。但是,由于某种原因,operator() 的签名中没有 const 说明符。这是什么意思,我应该如何将分布作为函数参数传递?我以为我必须将它作为任何非可变参数传递:通过 const 引用,但现在我不确定。

最佳答案

一开始我误解了这个问题,但是现在我明白了,这是一个很好的问题。一些深挖<random>的实现源码for 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 to 定义和声明将愉快地编译。

那么问题就变成了,对于其他所有发行版都是这样吗?答案是不。如果我们看一下 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 ,一切都变得有些困惑。

但是,为什么他们不简单地将它们设为 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";
}

这里,输出格式是mu sigma nextval .

关于c++ - 为什么 c++11 随机分布是可变的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16008271/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com