Lambda通过引用捕获引用变量

时间:2014-04-14 18:08:54

标签: c++ c++11 lambda

对于一个lambda,我想通过引用捕获一些东西,该引用已经通过引用保存在外部范围内。假设引用的值超出lambda,但不是lamdba创建的范围。

I know that如果lambda按值捕获引用变量,则将复制引用的对象。我想避免这个副本。

但是如果我通过引用捕获引用变量会发生什么?如果在执行lambda之前原始引用变量超出范围会怎么样?这样安全吗?换句话说:引用的引用后面的对象是lambda中引用的引用变量吗?

auto f() {
    const auto & myRef = g();
    return [&]{ myRef.doSomething(); };
}

f()();  // Safe?

1 个答案:

答案 0 :(得分:5)

是的,通过引用捕获对象的关键问题是引用对象的生命周期,而不是用于获取它的任何中间引用的生命周期。您可以将引用视为别名而不是实际变量。 (在类型系统中,引用与常规变量的处理方式不同。)引用别名原始对象,并且独立于用于别名对象的其他别名(除了它们为同一个对象设置别名的事实)。

<强> ===== EDIT =====

根据this SO question给出的答案(由 dyp 指出),似乎可能并不完全清楚。在整个语言的其余部分,参考&#34;参考的概念&#34;没有意义,从引用创建的引用成为该引用的对等体,但显然标准对于这种情况有些模棱两可,并且lambda捕获的引用在某种意义上可能是次要的,取决于堆栈帧从哪个他们被抓获了。 (SO答案引用的明确措辞特别指出了引用的实体,只要原始对象存在,表面上就会表明此用法是安全的,但绑定机制可能会将捕获链视为重要。)

我希望在C ++ 14/17中明确这一点,我希望澄清它以保证这种用法的合法性。特别是,我认为C ++ 14/17通过表达式捕获变量的能力将使通过堆栈帧指针简单地捕获作用域变得更加困难,而最明智的捕获机制通常是捕获特定实体个别。 (如果通过引用捕获实际的本地对象,则可能允许堆栈帧捕获,因为如果在任何情况下在范围外调用lambda,这将导致UB。)

在我们得到一些澄清之前,这可能无法移植。