为C++类播种rand()

Ale*_*lex 6 c++ random class static-variables random-seed

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

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

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

我的想法是这样的

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

    myVariable = rand()%maxVal;
}
Run Code Online (Sandbox Code Playgroud)

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

Ed *_* S. 6

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

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

// my_class.cpp
bool my_class::seeded = false;
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

    myVariable = rand() % maxVal;
}
Run Code Online (Sandbox Code Playgroud)


bam*_*s53 5

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

而不是为rand()新API提供单个全局(或每个线程)状态,通过将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';
}
Run Code Online (Sandbox Code Playgroud)

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