C++ 使用绑定与使用带有随机数生成器的指针
我的代码中有以下实现:C++ 使用绑定与使用带有随机数生成器的指针,c++,c++11,C++,C++11,我的代码中有以下实现: // 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_c
// 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;
}
考虑到您应该只有一个PRNG对象,并且您应该为它设定一次种子,然后每次需要新的随机数时都调用该对象,因为种子用于在PRNG中创建一系列随机数。我可以清楚地看到,第一种解决方案就是这样。
问题是,
bind()
在幕后是如何工作的?是不是每次调用都会创建一个新对象?它真的是调用(构造函数)
还是调用函数()
?它怎么知道该打哪一个?解决方案之间有什么不同吗?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;
};
struct随机调用
{
随机_调用(未签名种子)
:_mt19937_64(种子)
,统一实数(0.0,1.0)
{}
双运算符(){
返回统一实数(_mt19937_64);
}
标准:mt19937_64_mt19937_64;
标准:均匀实分布均匀实分布;
};
所以在我看来,它看起来还不错(实际上相当聪明)
一个警告是,您可能不想复制binder对象-即使它是可复制的,复制它,然后对原始对象调用
operator()
,副本将产生相同的数字。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;
};
struct随机调用
{
随机_调用(未签名种子)
:_mt19937_64(种子)
,统一实数(0.0,1.0)
{}
双运算符(){
返回统一实数(_mt19937_64);
}
标准:mt19937_64_mt19937_64;
标准:均匀实分布均匀实分布;
};
所以在我看来,它看起来还不错(实际上相当聪明)
一个警告是,您可能不想复制活页夹对象-即使它是可复制的,复制它,然后对原始对象调用
operator()
,副本将产生相同的数字。古老的格言“您应该只有一个PRNG对象”谢天谢地,随着C++11随机数库的出现,它消失了。@Bathsheba,你能详细说明一下吗?参考?古老的格言“你应该只有一个PRNG对象”谢天谢地随着C++11随机数库的出现而消失了。@Bathsheba你能详细解释一下吗?参考资料?@BinaryA肯定有。你不必为解除分配(在指针上调用delete
)和所有所有权之类的事情而烦恼,而且你还保存了一级间接寻址。指针是邪恶的,因为它们需要内存分配、生命周期管理,而且每次使用都需要取消引用。C++不是C语言。如果可以的话,请始终选择“对象是一个值”而不是“指向对象的指针”。@RichardHodges:顺便说一句,第一个解决方案可能没有指针,所以主要区别在于公开std::function
与公开
。这是一个合理的观点,但如果是关于隐藏实现细节,那么简单的pimpl就可以做到这一点,而且根本不需要任何std::headers?@BinaryA肯定有。你不必为解除分配(在指针上调用delete
)和所有所有权之类的事情而烦恼,而且你还保存了一级间接寻址。指针是邪恶的,因为它们需要内存分配、生命周期管理,而且每次使用都需要取消引用。C++不是C语言。如果可以的话,请始终选择“对象是一个值”而不是“指向对象的指针”。@RichardHodges:顺便说一句,第一个解决方案可能没有指针,所以主要区别在于公开std::function
与公开
。这是一个合理的观点,但如果是关于隐藏实现细节,那么简单的pimpl就可以做到这一点,而且根本不需要任何std::header?