Lambda通过引用捕获引用变量

lee*_*mes 6 c++ lambda c++11

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

我知道如果lambda 按值捕获引用变量,则会复制引用的对象.我想避免这个副本.

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

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

f()();  // Safe?
Run Code Online (Sandbox Code Playgroud)

Ada*_*son 5

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

=====编辑=====

根据对这个问题的答案(由dyp指出),似乎这可能不完全清楚.在整个语言的其余部分,"引用参考"的概念没有意义,并且从引用创建的引用成为该引用的同位体,但显然该标准对于此案例和lambda捕获有些模棱两可.在某种意义上,引用可能是次要的,取决于捕获它们的堆栈帧.(SO答案引用的显式措辞专门调用引用的实体,只要原始对象存在,表面上的表示这种用法是安全的,但绑定机制可能会将捕获链视为重要的.)

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

在我们得到一些澄清之前,这可能不是便携式的.

  • lambda中没有引用(不一定),因此没有引用参考."按引用捕获"是一个相当历史的术语,因为早期版本的lambdas为闭包类型指定了引用类型的数据成员.这已经在C++ 11之前被删除了,现在只在lambda内部指定了对实体*的访问(或者更确切地说,没有转换到另一个实体,因此访问了外部作用域的原始实体).这里的实体是一个声明为引用的变量. (4认同)