我有一个将 std::function
作为参数的类,我分配了一个 lambda 函数。它在构造函数中工作,但之后停止工作。调试器在运行第一行后说 f
是“空的”。为什么?
#include <iostream>
#include <string>
#include <functional>
typedef std::function<void(std::string)> const& fn;
class TestClass
{
public:
TestClass(fn _f) : f(_f) { F(); }
void F() { f("hello"); };
private:
fn f;
};
int main()
{
TestClass t([](std::string str) {std::cout << str << std::endl; });
t.F();
return 0;
}
调用 t.F()
会导致错误。为什么?
我可以通过将其更改为以下内容来解决它:
int main()
{
fn __f = [](std::string str) {std::cout << str << std::endl; };
TestClass t(__f);
t.F();
return 0;
}
但是,当我将 fn
更改为 auto
时,这同样不起作用!
int main()
{
auto __f = [](std::string str) {std::cout << str << std::endl; };
TestClass t(__f);
t.F();
return 0;
}
发生这种情况的原因是什么?
最佳答案
请注意 (1) fn
被定义为引用(对 const); (2) λ 和 std::function
不是同一类型; (3) 不能直接将引用绑定(bind)到不同类型的对象。
对于第一种情况,
TestClass t([](std::string str) {std::cout << str << std::endl; });
t.F();
创建临时 lambda,然后将其转换为 std::function
这也是暂时的。临时std::function
绑定(bind)到参数 _f
构造函数并绑定(bind)到成员 f
.这条语句后临时文件将被销毁,然后f
当 t.F();
时变得悬空它失败了。
对于第二种情况,
fn __f = [](std::string str) {std::cout << str << std::endl; };
TestClass t(__f);
t.F();
创建了一个临时的 lambda,然后将其绑定(bind)到引用(到 const)。然后它的生命周期被延长到引用的生命周期 __f
, 所以代码没问题。
对于第三种情况,
auto __f = [](std::string str) {std::cout << str << std::endl; };
TestClass t(__f);
t.F();
创建 lambda 然后转换为 std::function
这是一个临时的。临时std::function
绑定(bind)到参数 _f
构造函数并绑定(bind)到成员 f
.这条语句后临时文件将被销毁,然后f
当 t.F();
时变得悬空它失败了。
<支持>
(1) 你可以声明 fn
作为非引用,如 typedef std::function<void(std::string)> fn;
, 然后 std::function
将被复制,每个案例都会运作良好。
(2) 不要使用双下划线开头的名称,它们在 C++ 中是保留的。
关于c++ - std::functions 和 lambda 函数传递,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38831661/