C++类成员default_random_engine按引用传参后外部引擎未更新问题
问题描述
已知要让随机引擎在函数调用后同步更新内部状态,需要按引用方式传递引擎参数。但实际开发中遇到问题:在类构造函数里按引用传入随机引擎时,类外部的引擎状态并不会随类内的随机数生成操作同步更新。
预期效果是类内调用随机数生成方法后,外部的main_engine状态会同步改变,但实际运行后外部引擎状态仍停留在初始种子值123。
最小可复现代码
#include<iostream> #include<random> class rv{ public: std::default_random_engine rv_eng; rv(std::default_random_engine & eng){ this->rv_eng = eng; } double nd(){ std::normal_distribution<double> ndist {0.0, 1.0}; double draw = ndist(this->rv_eng); return draw; } }; int main(){ std::default_random_engine main_engine; main_engine.seed(123); std::cout << main_engine << std::endl; rv rv_instance(main_engine); std::cout << rv_instance.nd() << std::endl; std::cout << main_engine << std::endl; return 0; }
实际运行输出
123 -0.331232 123
产生原因
核心问题是类内的引擎成员是独立实例,而非外部引擎的引用:
- 你虽然在构造函数的参数列表里用引用类型接收外部传入的引擎,但类成员
rv_eng本身是一个独立的std::default_random_engine对象,和外部的main_engine是两个完全独立的实例。 - 构造函数内的
this->rv_eng = eng;执行的是拷贝赋值操作:只是把外部传入引擎的当前状态复制了一份给类内部的rv_eng,执行完这行之后两者就没有任何关联了。 - 后续调用
nd()方法生成随机数时,所有状态更新都作用在内部拷贝出来的rv_eng实例上,完全没有修改外部的main_engine,因此外部引擎的状态始终保持初始值。
修正方法
如果需要类内操作直接修改外部传入的原引擎,有两种常见实现方式:
- 将类内的引擎成员定义为引用类型,并且必须在构造函数的初始化列表中完成绑定(引用无法在构造函数体内通过赋值重绑定),参考代码如下:
class rv{ public: // 成员定义为随机引擎的引用,不再是独立实例 std::default_random_engine &rv_eng; // 初始化列表中直接绑定外部传入的引擎 rv(std::default_random_engine & eng): rv_eng(eng) {} double nd(){ std::normal_distribution<double> ndist {0.0, 1.0}; return ndist(rv_eng); } };
- 如果后续需要动态切换类绑定的随机引擎,可以把成员改成
std::default_random_engine*指针类型,构造时传入外部引擎的地址,调用生成随机数时解引用即可。
内容的提问来源于stack exchange,提问作者ThePunisher
相关产品推荐
相关产品推荐

