我想使用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();
答案 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