作为成员变量的lambda函数崩溃

ore*_*uro 8 c++ random lambda functional-programming c++11

该类montecarlo包含lambda作为成员变量.此代码可以编译,但会在运行时导致"分段错误(核心转储)".你能解释一下如何解决它吗?

#include<random>
#include<functional>
#include<iostream>

class montecarlo
{
  public:
    montecarlo(double x_min, double x_max);
    std::function<double()> rand;
};

montecarlo::montecarlo(double x_min, double x_max){
  std::random_device rd;
  std::mt19937 mt(rd());
  std::uniform_real_distribution<double> rand_(x_min, x_max); 
  rand = [&](){return rand_(mt);};
}

int main(){
  montecarlo x(0, 1);
  std::cout<<x.rand()<<std::endl;
}
Run Code Online (Sandbox Code Playgroud)

让我想知道的是,当我将构造函数的实现更改为下面的代码时,它工作正常:

montecarlo::montecarlo(double x_min, double x_max){
  rand = [](){return 0;};
}
Run Code Online (Sandbox Code Playgroud)

你可能知道,但让我说我想要做的不仅仅是使用随机函数.

son*_*yao 9

你想要捕捉rand_mt参考; 它们是内部的本地对象montecarlo::montecarlo,当在外部调用lambda时,montecarlo::montecarlo这些本地对象已经被破坏,并且存储在lambda对象中的引用已经被悬空.

您可以将其更改为按副本捕获; 并注意你需要使lambda mutable使调用rand_有效.例如

rand = [=]() mutable {return rand_(mt);};
Run Code Online (Sandbox Code Playgroud)


Mar*_*k R 5

这是未定义的行为,应该以Segmentation Fault结束.请注意,您的lambda通过引用捕获所有内容,它捕获的生命周期变量仅限于构造函数处理.因此,当使用lambda时,它可以处理不再存在的变量.

要修复它,将lambda更改为通过复制捕获变量,它将起作用.

或者将此变量设为类的字段.

  • "应该以Segmentation Fault结尾的未定义行为"是一个不合理的行为.根据定义,未定义的行为对必须或应该或可能发生的事情没有任何限制**. (9认同)