Lambda 捕获 'this' 保存为 std::function

Posted

技术标签:

【中文标题】Lambda 捕获 \'this\' 保存为 std::function【英文标题】:Lambda capture 'this' saved as std::functionLambda 捕获 'this' 保存为 std::function 【发布时间】:2018-02-10 01:18:46 【问题描述】:

以下代码使用 C++14 编译正常,但运行它会导致分段错误。这是由 lambda 函数捕获引起的(用问号注释)吗?正确的方法是什么?提前致谢。

#include <functional>
#include <iostream>
#include <memory>

struct Process 
    Process(std::function<void()> &processFunc) 
        : processFunc(processFunc) 
    void doit() 
        processFunc();  // causes segmentation fault
    

    std::function<void()> &processFunc;
;

struct Foo 
    Foo() 
        std::function<void()> func = [this]()this->process();; // ?
        p = std::make_unique<Process>(func);
    
    void process() std::cout << "Done.\n";
    void start() p->doit();
    std::unique_ptr<Process> p;
;

int main()

    Foo foo;
    foo.start();

【问题讨论】:

【参考方案1】:

发生分段错误是因为Process::processFunc 所引用的std::function 对象在Foo 构造函数返回时被破坏。要解决此问题,请让Process 保留std::function 对象的副本。

struct Process 
    Process(const std::function<void()>& processFunc) 
        : processFunc(processFunc) 
    // ...
    std::function<void()> processFunc;
;

【讨论】:

@ArnavBorborah 是的 好吧,为了完整起见,您可能需要考虑添加这是由您的答案中的悬空引用引起的。 @JiveDadson 我不明白五规则在这里是如何应用的。事实上,我会说这是一个“零规则”类。 很公平。我看的不够仔细。我认为构造函数是一个复制构造函数。 太棒了!非常感谢。

以上是关于Lambda 捕获 'this' 保存为 std::function的主要内容,如果未能解决你的问题,请参考以下文章

如何在lambda中按值捕获`this`和局部变量?

为啥捕获 lambda 不能应用于 std::valarray?

如何在标准函数 lambda c++ 11 中正确捕获参数包

是否可以提取 lambda 的捕获列表?

在 lambda 中捕获 std::array

如何从 C++14 中的广义 lambda 捕获返回包含 std::unique_ptr 的 std::function?