我在一个类中有一个函数,它定义了一个 lambda 并将它存储在一个局部静态变量中:
class A
{
public:
void call_print()
{
static auto const print_func = [this] {
print();
};
print_func();
};
virtual void print()
{
std::cout << "A::print()\n";
}
};
class B : public A
{
public:
virtual void print() override
{
std::cout << "B::print()\n";
}
};
我还执行了以下测试:
int main()
{
A a;
B b;
a.call_print();
b.call_print();
}
( Live Sample )
我期望打印的是:
A::print()
B::print()
但我真正得到的是:
A::print()
A::print()
(每个也打印相同的对象地址)
我怀疑这是由于 this
捕获造成的。我假设它会在调用时捕获 this
的值,但是它似乎在定义 lambda 时就被捕获了。
有人能解释一下 lambda 捕获的语义吗?他们什么时候真正被提供给函数?是所有捕获类型都相同,还是 this
是一个特例?删除 static
解决了这个问题,但是在我的生产代码中,我实际上将 lambda 存储在一个稍重的对象中,该对象代表我稍后插入信号的插槽。
最佳答案
这与 lambda 捕获的语义无关。这就是 static
的工作原理。
static
函数范围的变量被初始化一次。在你的整个程序中只有一个这样的对象。它将在第一次调用函数时被初始化(更具体地说,第一次执行 static
语句时)。因此,用于初始化 static
变量的表达式只会被调用一次。
因此,如果 static
函数范围的变量使用基于函数参数之一的数据(如 this
)进行初始化,那么它只会从该函数的第一次调用。
您的代码创建了一个 lambda。它不会在每次调用函数时创建不同的 lambda。
您似乎想要的行为不是函数局部 static
变量,而是对象成员。因此,只需在类本身中放置一个 std::function
对象,如果它为空则让 call_print
对其进行初始化。
关于c++ - 什么时候在 lambda 中捕获 'this'?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38354923/