gpt4 book ai didi

c++ - Lambda 通过引用捕获右值引用

转载 作者:太空狗 更新时间:2023-10-29 20:50:15 33 4
gpt4 key购买 nike

下面的代码是标准正确的吗? ( godbolt )

即by-ref 捕获代表临时的转发引用,并从函数返回生成的 lambda by-value,在同一表达式中

当然,存储 lambda 以备后用会使它包含悬空引用,但我指的是 main 中的确切用法。

我的疑虑与 this SO answer 有关并且可能是 this language defect .具体来说,有一条令人生畏的评论说“标准引用中的引用捕获生命周期规则捕获变量,而不是数据及其范围” - 这似乎是说捕获的对临时对象的引用可能无效我的代码。

#include <stdlib.h>
#include <string.h>
#include <cassert>

template<typename F>
auto invoke(F&& f)
{
return f();
}

template<typename F>
auto wrap(F&& f)
{
return [&f]() {return f();}; // <- this by-ref capture here
}

int main()
{
int t = invoke(wrap(
[]() {return 17;}
));

assert(t == 17);
return t;
}

最佳答案

在相对较短的历史时间窗口内,您的代码中存在 UB。 (注意:这是一个很奇怪的说法)。原始的 lambda 按引用捕获规则声明引用仅在捕获的变量超出范围之前有效。

无论是在当前标准下,还是在每个追溯修订的过去标准下,您的代码中都没有 UB。

这可能导致一种按引用捕获,否则在 C++ 标准中是不可能的。 (您可以获得的最接近的是对包含引用的单成员结构的引用)

理论上,您可以使用该事实使 lambda 引用捕获基于堆栈框架;捕获当前堆栈帧,并且所有(几乎?)引用参数都将位于该堆栈帧的固定偏移处。

由于大多数(所有?)ABI 在后台将引用参数实现为指针,这将导致函数参数的引用参数是在 lambda 返回后悬空的引用。

没有编译器利用这个事实。该优化从未使用过,只是尽可能地观察到。 “lambda 的引用捕获具有变量引用的生命周期”规则从未被任何编译器(或至少我听说过的任何编译器)利用。

当它被发现时,它在标准中被解决为缺陷解决方案,这意味着它追溯地重新定义了什么 意思是。

所以在历史下编译器这在技术上是 UB,没有当前兼容 编译器可以将其视为 UB,并且所有历史 C++11 编译器都以与当前编译器相同的方式对待它。所以你是安全的。

关于c++ - Lambda 通过引用捕获右值引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55559308/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com