为什么lambda通过引用捕获仍可与悬空引用一起使用?

问题描述

令我惊讶的是,以下C ++程序:

#include <iostream>
#include <functional>


int main() {
    std::function<void(void)> f;
    {
        int x = 1;
        f = [&x]() { std::cout << x; };
    }
    //std::cout << x;  // error: use of undeclared identifier 'x'
    f();               // no error!
    return 0;
}

输出:

1

与取消注释行时,我期望获得与输出相同的输出:

error: use of undeclared identifier 'x'

因为lambda f通过引用捕获了自动变量x (不是 by value ),并且x不在调用点f()的上下文(因此x主体中的f是一个悬空引用)。

为什么通过引用捕获lambda仍可与悬挂的引用一起使用?

解决方法

它不起作用。这只是它显示1的一个巧合。恰好是在调用lambda时,它驻留在捕获的地址中的某个值可以解释为带值1的int类型。

lambda的生存期大于变量的生存期。变量x在右花括号处被破坏,但是lambda仍然保留对其的引用。任何访问该引用的尝试都会导致未定义的行为。

在lambda声明中,您告诉要捕获的内容。使用声明它的地方的当前范围。调用lambda时,您告诉何时进行捕获。因此,与您的问题中的参考文献相比,它可以进行编译。但是,您有责任提供所使用变量的正确生命周期。

,

为什么lambda通过引用捕获仍可与悬空引用一起使用?

这是未定义的行为,因此可能有任何原因说明其工作方式。如果您使用以下代码编译代码:

在这里尝试:https://godbolt.org/z/5dd5sM

clang++ -O3 -fsanitize=address

您将立即获得:

ERROR: AddressSanitizer: stack-use-after-scope on address ....
READ of size 4...

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...