为什么通过引用捕获 lambda 仍在使用悬空引用?
Why does lambda capture by reference is still working with dangling references?
令我惊讶的是,以下 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
并且x
在调用 f()
时不在上下文中(因此 f
正文中的 x
是悬空引用)。
为什么通过引用捕获的 lambda 仍然适用于悬挂引用?
它不起作用。这只是它显示 1 的巧合。只是在调用 lambda 时驻留在捕获的地址中的某些值包含可以解释为值为 1 的 int 类型的值。
lambda 的生命周期大于变量的生命周期。变量 x 在右花括号处被销毁,但 lambda 仍然持有对它的引用。任何访问该引用的尝试都会导致未定义的行为。
在 lambda 声明中,您告诉 要捕获什么。使用声明的地方的当前范围。在调用 lambda 时,您告诉 何时 捕获。这就是为什么它与您问题中的引用相比进行编译的原因。但您有责任提供所用变量的正确生命周期。
Why does lambda capture by reference is still working with dangling references?
这是未定义的行为,因此可能有任何原因可以解释为什么它会以这种方式工作。如果您使用以下代码编译代码:
在这里试试:https://godbolt.org/z/5dd5sM
clang++ -O3 -fsanitize=address
您将立即获得:
ERROR: AddressSanitizer: stack-use-after-scope on address ....
READ of size 4...
令我惊讶的是,以下 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
并且x
在调用 f()
时不在上下文中(因此 f
正文中的 x
是悬空引用)。
为什么通过引用捕获的 lambda 仍然适用于悬挂引用?
它不起作用。这只是它显示 1 的巧合。只是在调用 lambda 时驻留在捕获的地址中的某些值包含可以解释为值为 1 的 int 类型的值。
lambda 的生命周期大于变量的生命周期。变量 x 在右花括号处被销毁,但 lambda 仍然持有对它的引用。任何访问该引用的尝试都会导致未定义的行为。
在 lambda 声明中,您告诉 要捕获什么。使用声明的地方的当前范围。在调用 lambda 时,您告诉 何时 捕获。这就是为什么它与您问题中的引用相比进行编译的原因。但您有责任提供所用变量的正确生命周期。
Why does lambda capture by reference is still working with dangling references?
这是未定义的行为,因此可能有任何原因可以解释为什么它会以这种方式工作。如果您使用以下代码编译代码:
在这里试试:https://godbolt.org/z/5dd5sM
clang++ -O3 -fsanitize=address
您将立即获得:
ERROR: AddressSanitizer: stack-use-after-scope on address ....
READ of size 4...