我发现如果lambda是一个调用自身的递归函数,那么它就不能被另一个lambda捕获,就像在C ++中的闭包中一样。
我有一些这样的代码:
#include <memory>
#include <functional>
#include <iostream>
class ClassA
{
public:
std::function<void()> FuncA;
void Call()
{
FuncA();
}
};
class ClassB
{
std::unique_ptr<ClassA> pA = std::make_unique<ClassA>();
public:
void Setup()
{
std::function<void(int)> FuncB = [&](int a)
{
std::cout << "a = " << a << std::endl;
if(a > 0)
FuncB(a-1);
};
pA->FuncA = [&]()
{
FuncB(10.0f);
};
}
void Run()
{
Setup();
pA->Call();
}
};
int main() {
ClassB B;
B.Run();
}
运行调用FuncA时会发生异常,因为其中的FuncB将是一个空指针。
我的问题是为什么我无法捕获递归的lambda函数?
我正在使用Visual Studio 2015
编辑: 如果在FuncA中通过复制捕获FuncB,那么如果FuncB不是递归的,则它可以工作。像这样:
class ClassB
{
std::unique_ptr<ClassA> pA = std::make_unique<ClassA>();
public:
void Setup()
{
std::function<void(int)> FuncB = [FuncB](int a)
{
std::cout << "a = " << a << std::endl;
if (a > 0)
FuncB(a - 1);
};
pA->FuncA = [FuncB]()
{
FuncB(10.0f);
};
}
void Run()
{
Setup();
pA->Call();
}
};
答案 0 :(得分:3)
您通过引用抓取FuncB
,但FuncB
在Setup
返回时被销毁,让您留下悬空参考。
如果更改FuncB
以按值捕获,则第一个lambda会在初始化之前捕获它,这会导致未定义的行为。
我无法想办法让lambda捕获自己,就像你想要做的那样。
答案 1 :(得分:1)
对您的代码进行了少量修改,这很好用:
#include <iostream>
#include <functional>
struct A
{
std::function<void()> fa;
void call() { fa(); }
};
struct B
{
A *pA;
B() {pA=nullptr; }
typedef std::function<void(int)> FB;
FB fb;
void Setup()
{
fb=[&](int i)
{
std::cout << "i = " << i << "\n";
if(i > 0) fb(i-1);
};
if (pA) { pA->fa=[&]() { fb(10.0f); }; }
}
void Run(A*p)
{
pA=p;
Setup();
pA->call();
}
};
int main()
{
A a;
B b;
b.Run(&a);
return 0;
}
也许这会帮助您优化算法。