首页 >后端开发 >C++ >C 11 Lambda 能否在不调用未定义行为的情况下捕获引用?

C 11 Lambda 能否在不调用未定义行为的情况下捕获引用?

Susan Sarandon
Susan Sarandon原创
2024-11-04 22:03:02681浏览

Can C  11 Lambdas Capture References Without Invoking Undefined Behavior?

在 C 11 Lambda 中捕获引用

在 C 中,lambda 表达式可以从其封闭范围捕获变量。然而,捕获的方法决定了变量是通过引用还是通过值访问。考虑以下代码:

<code class="cpp">#include <functional>
#include <iostream>

std::function<void()> make_function(int& x) {
    return [&]{ std::cout << x << std::endl; };
}

int main() {
    int i = 3;
    auto f = make_function(i);
    i = 5;
    f();
}</code>

此代码使用 [&] 语法通过引用捕获变量 x。问题是这个程序是否保证在不调用未定义行为的情况下输出 5。

答案:是

代码保证正确工作。在检查底层标准措辞之前,重要的是要注意此代码的功能符合 C 委员会的预期。然而,C 11 标准的最初措辞在这一问题上并不清楚,导致 CWG 问题 2011 被提出来提供澄清。这个问题正在C标准的持续开发中得到解决。

标准解释

根据C标准的[expr.prim.lambda]/17,只有引用复制捕获的实体的 id 表达式才会转换为 lambda 闭包类型的成员访问。引用通过引用捕获的实体的 id 表达式将被保留,并继续表示它们在封闭范围中表示的相同实体。

在上面的代码中,捕获的实体是 make_function 函数的参数 x ,落在 lambda 的可达范围内。因此,lambda 表达式中的引用 x 引用了在 main 函数中声明的原始变量。

在 make_function 函数返回后,在 x 的生命周期之外引用 x 最初可能会出现问题。但是,在有限的情况下,可以在引用的生命周期之外对其进行引用。一般来说,引用要么在作用域中声明,要么是类成员,在这种情况下,类本身必须在其生命周期内。

因此,标准没有明确禁止在其生命周期之外使用引用。此漏洞允许支持在 lambda 表达式中通过引用捕获引用。

CWG 2012 期问题和未来澄清

提出 CWG 2012 期问题是为了解决监督问题在某些情况下,引用可以在其生命周期之外被引用。此问题的解决无意中影响了通过引用引用捕获 lambda 的规范。不过,预计此回归将在 C 17 发布之前修复。

以上是C 11 Lambda 能否在不调用未定义行为的情况下捕获引用?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn