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