为C ++类播种rand()

时间:2012-11-04 02:23:29

标签: c++ class random static-variables random-seed

我正在开发一个在构造函数中使用rand()的C ++类。我真的希望这个课程能够在各方面照顾自己,但我不确定在哪里播种rand()

如果我在构造函数中对rand()进行种子处理,则每次构造对象类型的新实例时都会对其进行种子处理。因此,如果我按顺序创建3个对象,它们将在同一秒内创建,因此rand()具有相同的种子,为对象的3个实例中的每个实例生成完全相同的数据。

我想在类代码中播种rand(),而不是在创建对象之前必须在程序的main函数中执行它。我想过做一个static bool seeded;变量来表示rand()是否已被播种,但我不确定如何在创建类时将其初始化为false。

我的想法类似于

myConstructor(){
    if(!seeded){
        srand(time(NULL));
        seeded = true;
    }

    myVariable = rand()%maxVal;
}

我认为如果我能弄清楚如何在程序开始时将静态值初始化为false,那么这将有效。我的理解是,如果对象的所有实例都是静态的,那么将此静态值更改为true将会传递该对象的所有实例,因此只会在第一次创建对象类型时执行种子函数。

5 个答案:

答案 0 :(得分:6)

  

我认为如果我能弄清楚如何在程序开始时将静态值初始化为false,那么这将有效。

// my_class.h
class my_class {
public:
  // ...
private:
  static bool seeded;
};

// my_class.cpp
bool my_class::seeded = false;

确保在实现文件中定义seeded。否则,包含标头的每个文件都将获得自己的静态成员定义,并且它也可能导致链接器问题,因为它可以多次定义。

另外,如果静态成员是const整数类型,您可以在声明点分配它。

另一个选择就是这个,我个人更喜欢这个任务:

my_class::my_class()         
{
    static bool seeded = false;
    if(!seeded) {
        srand(time(NULL));
        seeded = true;
    }

    myVariable = rand() % maxVal;
}

答案 1 :(得分:5)

此问题是使用rand()的问题之一。 C ++ 11引入了<random>库来解决这个问题和其他问题。

新API不是为rand()提供单个全局(或每个线程)状态,而是通过将RNG封装在具有值语义的对象中,使您可以明确控制RNG的状态。

您可以将状态维护为成员变量,或者作为静态成员,如果您希望所有实例共享一个,或者其他任何有意义的用途。

#include <random> // for mt19937, uniform_int_distribution
#include <chrono> // for high_resolution_clock
#include <iostream>

struct C {
    // Hold RNG state as a member variable
    std::mt19937 eng{std::chrono::high_resolution_clock::now().time_since_epoch().count()};

    int foo() {
        // use the member variable to generate random numbers in a member function.
        return std::uniform_int_distribution<>(1,10)(eng);
    }
};

int main() {
    C c, d;
    std::cout << c.foo() << '\n';
    std::cout << d.foo() << '\n';
}

(上面使用除<random>之外的一些C ++ 11特性; <chrono>库用于非静态成员的时间,统一初始化和类内初始化。)

答案 2 :(得分:2)

使用仅初始化一次的静态变量功能:

static bool seed()
{
  srand(time(NULL));
  return true;
}
myConstructor(){
  static bool seeded = seed();
  myVariable = rand()%maxVal;
}

答案 3 :(得分:1)

问题类似于单例实例化。使用您的操作系统功能,例如pthread_onceboost::call_oncestatic成员,只执行一次种子。

答案 4 :(得分:0)

bames53有一个很好的答案。现在将所有内容完美地转换为独立的整数生成函数:

int generateRandom(int min, int max) {
   std::mt19937 eng{std::chrono::high_resolution_clock::now().time_since_epoch().count()};
   return std::uniform_int_distribution<>(min,max)(eng);
}