假设我有以下内容。
struct A
{
int x;
std::function<int()> f1() { return [=](){ return x; }; }
std::function<int()> f2() { return [=](){ return this->x; }; }
std::function<int()> f3() { return [this](){ return x; }; }
std::function<int()> f4() { return [this](){ return this->x; }; }
std::function<int()> f5()
{
int temp = x;
return [=](){ return temp; };
}
}
现在我有以下代码。
auto a = std::make_shared<A>();
a->x = 5;
std::function<int()> f = a.f#();
a.reset();
int x = f();
其中f#
指的是f1, f2, f3, f4, f5
中的任何一个。
这些功能在两组之一中表现出行为:
f5
)或nullptr
(f1, f2, f3, f4
)。我理解这是因为有些人在this
的成员函数中隐式或明确地捕获“A
”。
确定行为1或2的正式规则是什么?
我花了一段时间处理由f1
类似的错误导致的错误,认为它会捕获x
并且从不认为它会捕获this
,所以我认为它会记录下来是有用的。
答案 0 :(得分:8)
没有正式规则可以确定此行为。因为此行为是未定义。
你的lambda正在访问一个不存在的对象。您无法直接按值捕获成员变量;你总是通过this
捕获它们。这意味着您通过引用捕获它们。删除对象后,任何访问该已删除对象的尝试都会导致未定义的行为。
这个例外是f5
,它应该保证一致的值。它与原始对象完全断开。