C ++;使用lambdas有条件地扩展类中的函数(与MWE的seg错误)

时间:2018-04-04 09:37:41

标签: c++ lambda this self-reference

我想使用lambdas有条件地扩展类中函数的功能。在类范围之外执行此操作没有问题(参见示例),但是当调用在类中修改了自身的函数时,下面的最小工作示例会导致分段错误。任何人都可以解释为什么这个代码失败了,我应该如何考虑类中的lambdas而不是类之外的lambdas?

#include <functional>
#include <iostream>

class MyClass 
{
  public:
    MyClass(bool modify);
    int a;
    std::function<void (void)> myFunc;
};

MyClass::MyClass(bool modify) 
{
    a = 2;
    myFunc = [this](){ std::cout << "1. Inside my initialized function; a=" 
                                 << this->a << std::endl;};
    //myFunc(); -- works with or without being commented
    if (modify)
    {
        myFunc = [this](){ this->myFunc(); 
                           std::cout << "2. adding an output line to my "
                                     << "initialized function" << std::endl;};
        //EDIT: Originally tried
        //       myFunc = [myFunc](){ myFunc(); std::cout << endl; };
        //       but this will not compile.  See edit of post below
        //myFunc(); -- fails with or without being commented
    }
}

int main(int argc, char **argv) 
{
    std::function<void (void)> func;
    int a = 2;
    func = [a](){ std::cout << "1. Inside my initialized function; a=" 
                            << a << std::endl;};
    func = [func](){ func(); 
                     std::cout << "2. adding an output line to my initialized "
                               << "function" << std::endl;};
    std::cout << "Result of modified function outside of class: " << std::endl;
    func();
    std::cout << std::endl;

    std::cout << "Result of unmodified function in class: " << std::endl;
    MyClass myClassNoMod(false);
    myClassNoMod.myFunc();
    std::cout << std::endl;

    std::cout << "Result of modified function in class: " << std::endl;
    MyClass myClassMod(true);
    myClassMod.myFunc();

    return 0;
}

修改 PaulR提供了在myFunc更新中捕获this而不是myFunc的合理建议。在我最初的实现中,这是我尝试过的:

myFunc = [myFunc](){myFunc(); std::out << "stuff\n"; };

但这会导致编译错误

error: 'myFunc' in capture list does not name a variable
        myFunc = [myFunc](){ myFunc();
                  ^
error: 'this' cannot be implicitly captured in this context
        myFunc = [myFunc](){ myFunc();

1 个答案:

答案 0 :(得分:4)

在你的班级中你捕获myFunc指针而不是myFunc的前一个值,因此你的lambda会递归地自我调用,因为在调用时main成员已经是换成了新的lambda。

func中,您可以按值捕获myFunc的上一个值,从而达到预期效果。

所以我建议按值(即没有&amp;)而不是this来抓取if (modify) { auto previousFunc = std::move(myFunc); myFunc = [previousFunc](){ previousFunc(); std::cout << "2. adding an output line to my " << "initialized function" << std::endl;}; } 的副本。

if (modify)
{
    myFunc = [previousFunc{std::move(myFunc)}](){ previousFunc(); 
                       std::cout << "2. adding an output line to my "
                                 << "initialized function" << std::endl;};
}

如果您使用的是C ++ 14或更高版本,您还可以使用lambda capture expressions来避免复制并直接将上一个函数移动到lambda捕获中:

id