Lambda通过引用捕获右值引用 [英] Lambda capturing rvalue reference by reference

查看:487
本文介绍了Lambda通过引用捕获右值引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Is below code standard-correct? (godbolt)

即by-ref捕获表示临时引用的转发引用,并从函数在同一表达式内返回结果的lambda按值.

I.e. by-ref capturing a forwarding reference that represents a temporary, and returning the resulting lambda by-value from the function, within the same expression.

当然,存储lambda供以后使用会使它包含一个悬挂的引用,但是我指的是main内部的确切用法.

Of course storing the lambda for later use would make it contain a dangling reference, but I'm referring to the exact usage inside main.

我对此SO答案以及可能的标准引用中的引用捕获生存期规则捕获了变量,而不是数据及其作用域". –这似乎表明捕获的对临时变量的引用在以下情况下可能是无效的:我的代码.

The doubts I'm having relate to this SO answer and potentially this language defect. Specifically there is one daunting comment that says "the reference capture lifetime rule in the standard references captured variables, not data, and their scope" - this appears to say a captured reference to a temporary might be invalid in my code.

#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按引用捕获规则指出,该引用仅在捕获的变量超出范围之前有效.

There was UB in your code for a relatively short window. The original lambda capture-by-reference rules stated the reference was only valid until the variable captured went out of scope.

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

This could lead to a sort of capture reference-by-reference, otherwise impossible in the C++ standard. (The closest you could get would be a reference to a one-member struct containing a reference)

理论上,您可以利用这一事实使Lambda参考捕获基于堆栈框架;捕获当前的堆栈帧,并且所有(几乎?)按引用参数都将相对于该堆栈帧具有固定的偏移量.

In theory, you could use that fact to make lambda reference capture be stack-frame based; capture the current stack frame, and all (almost?) by-reference arguments would be at fixed offsets to that stack frame.

由于大多数(全部?)ABI在后台将引用参数实现为指针,这将导致函数参数的引用参数成为在lambda返回后悬挂的引用.

As most (all?) ABIs implement reference arguments as pointers under the hood, this would lead to reference arguments to functions arguments which are references dangling after the lambda returned.

没有编译器利用此事实.从未使用过这种优化,只是尽可能地观察到了. "lambda的引用捕获具有变量引用的生存期"规则从未被任何编译器(或至少我听说过的任何一个)利用.

No compiler exploited this fact. That optimization was never used, it was just observed as possible. The "reference capture of a lambda has a lifetime of the variable reference" rule was never exploited by any compiler (or at least any I heard of).

当发现它时,它已作为标准中的缺陷解决方案解决,这意味着它可追溯地重新定义什么的意思.

When it was spotted, it was resolved as a defect resolution in the standard, which means it retroactively redefined what c++11 meant.

因此,根据历史记录

登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆