我正在开发一个在构造函数中使用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将会传递该对象的所有实例,因此只会在第一次创建对象类型时执行种子函数。
答案 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_once
或boost::call_once
和static
成员,只执行一次种子。
答案 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);
}