C++;班 我在C++中使用构造函数中的 RAND()/。我真的希望这个类在几乎所有方面都能照顾好自己,但我不确定在哪里播种rand()

C++;班 我在C++中使用构造函数中的 RAND()/。我真的希望这个类在几乎所有方面都能照顾好自己,但我不确定在哪里播种rand(),c++,class,random,static-variables,random-seed,C++,Class,Random,Static Variables,Random Seed,如果我在构造函数中设置种子rand(),则每次构造对象类型的新实例时都会设置种子。因此,如果我按顺序创建3个对象,它们都将在同一秒钟内创建,因此具有相同的rand()种子,为对象的3个实例中的每一个生成完全相同的数据 我想在类代码中植入rand(),而不是在创建对象之前必须在程序的主函数中这样做。我想做一个静态bool seed变量,表示是否已为rand()设定种子,但我不确定如何在创建类时将其初始化为false 我的想法是这样的 myConstructor(){ if(!seeded)

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

我想在类代码中植入
rand()
,而不是在创建对象之前必须在程序的主函数中这样做。我想做一个
静态bool seed变量,表示是否已为
rand()
设定种子,但我不确定如何在创建类时将其初始化为false

我的想法是这样的

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

    myVariable = rand()%maxVal;
}
我想,如果我能在程序开始时找出如何将静态值初始化为false,这将是可行的。我的理解是,如果该对象是静态的,那么将该静态值更改为true将携带该对象的所有实例,因此只会在第一次创建该对象类型时执行seed函数

我想,如果我能在程序开始时找出如何将静态值初始化为false,这将是可行的

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

另一方面,如果静态成员是const integral类型,则可以在声明时指定它

另一个选择是这样,我个人更喜欢这样做:

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

    myVariable = rand() % maxVal;
}

这个问题类似于单例实例化。使用操作系统的功能,如
pthread\u once
boost::call\u once
static
成员,一次且仅一次执行种子。使用静态变量功能,仅初始化种子一次:

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

此问题是使用
rand()
时出现的问题之一。C++11引入了
库,它解决了这个问题和其他问题

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

您可以将状态维护为成员变量,或者如果希望所有实例共享一个,则可以将状态维护为静态成员,或者任何对您的使用有意义的内容

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

std::mt19937 seeded_engine() {
    std::random_device r;
    std::seed_seq seed{r(), r(), r(), r(), r(), r(), r(), r()};
    return std::mt19937(seed);
}

struct C {
    // Hold RNG state as a member variable
    std::mt19937 eng = seeded_engine();
    
    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';
}
#包括//对于mt19937,统一内部分布
#包括
std::mt19937种子_引擎(){
std::随机_装置r;
种子{r(),r(),r(),r(),r(),r(),r(),r(),r(),r(),r(),r()};
返回标准:mt19937(种子);
}
结构C{
//将RNG状态保留为成员变量
std::mt19937 eng=种子引擎();
int foo(){
//使用成员变量在成员函数中生成随机数。
返回标准:统一内部分布(1,10)(英语);
}
};
int main(){
C,d;

std::coutbames53有一个很好的答案。现在要将所有这些很好地拉入一个独立的整数生成函数:

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);
}
int-generateradom(int-min,int-max){
std::mt19937 eng{std::chrono::高分辨率时钟::now();
返回标准:均匀分布(最小值、最大值)(eng);
}

<代码> >我将远离<代码> RAND 并使用一个适当的随机数类,例如.@ PubBy。我想我可以在将来考虑这样的事情,但现在我要用这个项目来坚持标准库。初始化静态变量为false是非常微不足道的:<代码> int您的RealClass::S播种Ed= false;< /Cl>(在一个源文件中,而不是在类定义中).FWIW,@pubby建议的类是C++11标准库的一部分。@Alex,这是C++11标准库的一部分。哦,很高兴知道,我必须读一读。扫描他给我的链接时,我以为它是一个外部库。我以为我需要这样做,但我很难找到确切的链接我需要使用的语法。谢谢。@Alex:是的,它有点古怪,不是非常直观,但当你考虑它时,它是有意义的。在执行seed()之前,我是否还需要确保seed为false函数?这是否会导致在类的所有实例中只设置一次种子变量?@Alex:如果总是返回true,则不必测试种子是否为true。是的,它将只设置一次,即使在多线程环境中也能正常工作。@Alex静态变量的初始值设定项只执行一次,因此您不需要执行'不必检查任何内容。编译器将执行
seed()
一次,你不必担心这是如何实现的。这是一个非常好的技巧。我会尝试一下。我喜欢这个建议,但实际上我正在尽可能多地跨平台使用这个程序。使用特定于操作系统的函数会使我不得不更改每个操作系统的代码。嗯,
boost::call\u一次是跨平台的。但是,如果您只关心初始化时的并发性,只需要它或<代码> pthRead一次>代码。我想我应该多读一些关于这些函数的知识。它们将来可能会有很大的帮助。我肯定会再读一些关于这个的。我在C++中的训练似乎有点过时。
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);
}