Lambda表达式偷偷地捕获了' this '
Lambda expression sneakily capturing `this`
假设我有以下内容:
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
)或 时返回5 - 试图解引用
nullptr
(f1, f2, f3, f4
)时崩溃。
我理解这是因为有些人在A
的成员函数中隐式或显式地捕获了"this
"。
决定行为1或行为2的正式规则是什么?
我花了一段时间处理一个由类似f1
的东西引起的bug,认为它会捕获x
,从未考虑它会捕获this
,所以我认为把这个记录下来会很有用。
没有正式的规则来决定这种行为。因为此行为未定义。
你的lambda正在访问一个不存在的对象。不能直接按值捕获成员变量;你总是通过this
来捕捉它们。也就是说你是通过引用来捕捉它们的。一旦对象被删除,任何访问该对象的尝试都会导致未定义的行为。
例外是f5
,它应该返回一个一致的值,保证。它与原始对象完全断开。
相关文章:
- 表示"accepting anything for this template argument" C++概念的通配符
- 为什么使用 "this" 指针调用派生成员函数?
- (C++)分析树以计算返回错误值的简单算术表达式
- 在VS2010-VS2015下编译时,如何使用decltype作为较大类型表达式的LHS
- 提升精神:解析布尔表达式并简化为规范范式
- 不能在初始值设定项列表中将非常量表达式从类型 'int' 缩小到'unsigned long long'
- 使用正则表达式regex_search在字符串中查找字符串
- 如何确认我的constexpr表达式实际上已经在编译时执行
- 概念中的cv限定符需要表达式参数列表
- 为什么constexpr的性能比正常表达式差
- 对于结构,表达式必须是可修改的ivalue
- 当一个值是非常量但用常量表达式初始化时使用constexpr
- 将fold表达式与std::一起用于两个元组
- 整体模板参数。错误:在常量表达式中使用'this'
- 尝试使用指针时出现预期表达式"this"错误
- 关于默认捕获模式和 lambda 表达式C++"this"的限制
- 'this'不能用于常量表达式错误 (C++)
- 当我尝试caputre〔this〕时,用于回调函数的lambda表达式失败,原因是什么
- Lambda表达式偷偷地捕获了' this '
- GCC 内联程序集错误:无法获取"this"的地址,这是一个右值表达式