C++;使用 lambdas 在 class 中有条件地扩展一个函数(MWE 的段错误)
C++; using lambdas to conditionally expand a function within a class (seg fault with MWE)
我想使用 lambda 有条件地扩展 class 中函数的功能。在 class 范围之外执行此操作没有问题(参见示例),但下面的最小工作示例在调用在 class 内修改自身的函数时会导致分段错误。谁能解释为什么这段代码会失败,以及我应该如何看待 class 内的 lambda 与 class 外的 lambda?
#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
的更新中给出了捕获myFunc
而不是this
的合理建议。在我最初的实现中,这是我尝试过的:
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();
在您的 class 中,您捕获 this
指针而不是 myFunc
的先前值,因此您的 lambda 将永远递归调用自身,因为在调用时 myFunc
成员将已更改为新的 lambda。
在 main
中,您按值捕获了 func
的先前值,因此它会按照您的预期进行。
所以我建议按值(即不带 &)捕获 myFunc
的副本,而不是 this
。
if (modify)
{
auto previousFunc = std::move(myFunc);
myFunc = [previousFunc](){ previousFunc();
std::cout << "2. adding an output line to my "
<< "initialized function" << std::endl;};
}
如果您使用的是 C++14 或更新版本,您还可以使用 lambda capture expressions 来避免复制并直接将之前的函数移动到 lambda 捕获中:
if (modify)
{
myFunc = [previousFunc{std::move(myFunc)}](){ previousFunc();
std::cout << "2. adding an output line to my "
<< "initialized function" << std::endl;};
}
我想使用 lambda 有条件地扩展 class 中函数的功能。在 class 范围之外执行此操作没有问题(参见示例),但下面的最小工作示例在调用在 class 内修改自身的函数时会导致分段错误。谁能解释为什么这段代码会失败,以及我应该如何看待 class 内的 lambda 与 class 外的 lambda?
#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
的更新中给出了捕获myFunc
而不是this
的合理建议。在我最初的实现中,这是我尝试过的:
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();
在您的 class 中,您捕获 this
指针而不是 myFunc
的先前值,因此您的 lambda 将永远递归调用自身,因为在调用时 myFunc
成员将已更改为新的 lambda。
在 main
中,您按值捕获了 func
的先前值,因此它会按照您的预期进行。
所以我建议按值(即不带 &)捕获 myFunc
的副本,而不是 this
。
if (modify)
{
auto previousFunc = std::move(myFunc);
myFunc = [previousFunc](){ previousFunc();
std::cout << "2. adding an output line to my "
<< "initialized function" << std::endl;};
}
如果您使用的是 C++14 或更新版本,您还可以使用 lambda capture expressions 来避免复制并直接将之前的函数移动到 lambda 捕获中:
if (modify)
{
myFunc = [previousFunc{std::move(myFunc)}](){ previousFunc();
std::cout << "2. adding an output line to my "
<< "initialized function" << std::endl;};
}