如何在C++类中正确使用离散分布作为成员变量
解决C++类成员分布变量未正确初始化导致采样始终为0的问题
嘿,这个问题我刚好看过类似的,核心原因很简单:你在构造函数里重新定义了一个和类成员同名的局部变量,导致类的power_dist成员根本没被正确初始化!
问题根源
你在头文件里已经把power_dist声明为FastOnePlusOne的私有成员了,但在构造函数里写了:
std::discrete_distribution<int> power_dist(pmf.begin(),pmf.end());
这行代码创建了一个局部的power_dist变量,它和类成员是完全独立的两个对象。构造函数执行完后,这个局部变量就被销毁了,而类的power_dist成员还是默认构造的状态——std::discrete_distribution默认构造后,每次采样都会返回0,这就是为什么iterate()里的alpha始终是0。
修复方案
只需要去掉构造函数里的类型声明,直接给类成员变量赋值即可:
修改后的构造函数代码:
FastOnePlusOne::FastOnePlusOne(Random& _rand, shared_ptr<Evaluator> _evaluator, Configuration& _config) : Optimizer(_rand, _evaluator, _config) { // 幂律分布初始化 int length = 10; float B = 1.5; vector<double> pmf(length); std::iota(pmf.begin(), pmf.end(), 1); for(size_t i = 0; i < length; i++) { pmf[i] = 1.0 / pow(pmf[i], B); } pmf.insert(pmf.begin(), 0); // 直接给类成员变量赋值,不再定义新的局部变量 power_dist = std::discrete_distribution<int>(pmf.begin(),pmf.end()); std::map<int, int> m; for(int n=0; n<10000; ++n) { ++m[power_dist(_rand)]; // 顺便建议用传入的_random,而不是rand() } for(auto p : m) { std::cout << p.first << " generated " << p.second << " times\n"; } }
额外小建议
注意你代码里用的rand(),既然构造函数已经传入了Random& _rand参数,最好统一使用这个项目自带的随机数生成器,而不是C标准库的rand(),这样能保证随机数的质量和项目整体的一致性。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

