我的代码中有以下实现:
// first solution
//random.h
class Random{
public:
std::mt19937* gen;
std::uniform_real_distribution<double>* dis;
}
//random.cpp
Random::Random()
{
std::mt19937_64::result_type seed = chrono::high_resolution_clock::now().time_since_epoch().count();
gen = new std::mt19937(seed);
dis = new std::uniform_real_distribution<double>(0.0,1.0);
}
double Random::next()
{
double rand = 0;
rand_int = (*dis)(*gen);
return rand;
}
另一方面,公司中的其他人做了一个不同的实现,他使用了 c++11 中的 bind
功能,如下所示:
// second solution
//random.h
class Random{
public:
std::function<double()> real_rand;
}
//random.cpp
Random::Random()
{
std::mt19937_64::result_type seed = chrono::high_resolution_clock::now().time_since_epoch().count();
real_rand = std::bind(std::uniform_real_distribution<double>(0.0,1.0), mt19937_64(seed))
}
double Random::next()
{
double rand = 0;
rand = real_rand();
return rand;
}
考虑到您应该只有一个 PRNG 对象,并且您应该为它播种一次,然后每次您需要一个新的随机数时调用该对象,因为种子用于创建一系列PRNG 中的随机数。我可以清楚地看到第一个解决方案就是这种情况。
问题是,bind()
在幕后是如何工作的?它是否在每次调用时创建一个新对象?它真的调用了 (constructor)
还是 function()
?它怎么知道要调用哪一个?解决方案之间有什么区别吗?
最佳答案
std::bind
生成一个函数对象,它封装了提供给它的参数。实际上,您同事的代码会生成以下对象:
struct random_call
{
random_call(unsigned seed)
: _mt19937_64(seed)
, _uniform_real(0.0, 1.0)
{}
double operator() {
return _uniform_real(_mt19937_64);
}
std::mt19937_64 _mt19937_64;
std::uniform_real_distribution<double> _uniform_real;
};
所以对我来说它看起来不错(而且实际上非常聪明)!
需要注意的是,您可能不想制作 Binder 对象的任何拷贝 - 即使它被证明是可复制的,复制它然后在原始和上调用 operator()
拷贝将产生相同的数字。
关于c++ - 使用绑定(bind)与使用带有随机数生成器的指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31878138/