我有这段代码(简化):
void make()
{
std::random_device rd;
std::mt19937 generator(rd());
std::uniform_real_distribution<double> distribution(this->min, this->max);
const auto graphFunc = [this, generator, distribution](double x) -> double
{
return distribution(generator);
};
// ... use graphFunc
}
给出以下编译错误:
具有类型 'const std::mt19937' 的错误 C3848 表达式将丢失一些 const-volatile 限定符以调用 'unsigned int std::mersenne_twister<_Ty,32,624,397,31,2567483615,11,7,2636928640,15,4022730752,18 >::运算符 ()(void)' \microsoft visual studio 14.0\vc\include\random 316
对象rd的复制构造函数和赋值被声明为删除,从代码判断random.h
random_device(const random_device&) = delete;
random_device& operator=(const random_device&) = delete;
跟上面的代码有关系吗?- 在我看来它有,因为当generator复制到 lambda 时,它还必须调用rd被删除对象的复制构造函数
那么解决方法是什么?
这个编译错误的本质是什么?
看那里没有。要传递给分发,您需要一个可变的生成器对象——但您可以通过不可变的 lambda 中的值捕获它。
如果不更改 RNG 的状态,您将无法获得随机数 - 否则 RNG 每次都会给出相同的数字。
如果你扩展你的 lambda,你会得到这样的东西:
这里存在三个问题:
operator()声明为 const(不更改对象的状态)——这会阻止将对生成器的引用传递给分发。在定义中添加mutable一个 lambda 以operator()不再是 const。该变量被
graphFunc声明为 const - 这可以防止调用非常量方法。删除const。捕获
generator后,它会被复制——如果您在其他地方使用它,可能会导致不同序列之间出现虚假相关。您需要通过引用来捕获它。寄生关联示例:https ://ideone.com/boR272
解题示例:https ://ideone.com/lLnyfL
如果 lambda 生命周期长于局部变量生命周期 - 使用 std::shared_ptr 而不是引用。