使用绑定vs使用带有随机数生成器的指针

时间:2015-08-07 12:49:16

标签: 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_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()?它怎么能告诉哪个人打电话?这些解决方案之间有什么不同吗?

1 个答案:

答案 0 :(得分:4)

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;
};

所以它看起来很好(实际上非​​常聪明)给我!

有一点需要注意的是,您可能不希望制作活页夹对象的任何副本 - 即使它是可复制的,复制它然后在原始文件上调用operator(),副本将产生相同的数字。