无法按 lambda 中的值捕获随机分布和生成器?

Can not capture a random distribution and generator by value in lambda?

本文关键字:分布 随机 lambda      更新时间:2023-10-16

以下代码工作正常

#include <iostream>
#include <random>
int main() {
std::default_random_engine generator;
std::normal_distribution<double> distribution(5.0, 2.0);
std::vector<double> v(100);
std::generate(v.begin(), v.end(), [&] () { return distribution(generator); });
return 0;
}

但是,将 lambda 的捕获列表更改为[=][&, distribution][&, generator]原因

rand.cpp:9:59: error: no matching function for call to object of type 'const std::normal_distribution<double>'
error: assigning to 'double' from incompatible type 'void'

是否有某些类型的对象不能通过 lambda 中的值捕获?

看起来std::normal_distribution<double>::operator()不是const. 因此,您必须将mutable关键字添加到lambda中:

std::generate(v.begin(), v.end(), [=] () mutable { 
return distribution(generator); 
});
std::generate(v.begin(), v.end(), [&, distribution] () mutable { 
return distribution(generator); 
});

这些都可以正常工作。

通常,按值捕获要求对象是可复制的。std::default_random_generatorstd::normal_distribution都是可复制的,所以这应该不是问题。

Lambda 捕获始终是常量值或常量引用。随机数生成本质上是有状态的,因此被调用的operator()不能是常量,因为它可能会修改对象状态。错误消息神秘地报告了这一点,说没有函数可以调用const std::normal_distribution<double>

如果要修改捕获的对象,则必须将 lambda 声明为可变对象

#include <iostream>
#include <random>
#include <algorithm>
int main() {
std::default_random_engine generator;
std::normal_distribution<double> distribution(5.0, 2.0);
std::vector<double> v(100);
std::generate(v.begin(), v.end(), [generator, distribution] () mutable { return distribution(generator); });
return 0;
}