【问题标题】:Dangling reference in inner lambda [duplicate]内部 lambda 中的悬空引用
【发布时间】:2017-04-24 09:10:34
【问题描述】:

我有一个内部 lambda,它使用外部 lambda 的引用变量之一,如下所示:

int x=0;
auto outer=[&](){
   return [&](){
        x=5;
    };
};

auto inner= outer();
inner();
std::cout << x;

tried它。它运作良好。但是,我想确保这里没有悬空引用。有吗?

【问题讨论】:

  • 我的看法 - 它是对同一 x 的引用,并且由于您没有离开定义它的范围 - 它不是一个悬空引用。但是,我会让更多知识渊博的人回答它。

标签: c++ c++11 lambda dangling-pointer


【解决方案1】:

这里没有悬空引用。内部 lambda 的引用不是对引用的引用(没有这样的东西);它指的是x - 当然没有超出范围。

【讨论】:

  • 因此,确实不再存在“对引用的引用”之类的东西,而且从未真正存在过。但是在 C++11 中存在一个缺陷,它将 lambda 中引用捕获变量的生命周期与它们捕获的引用变量的生命周期联系起来,而不是与它们所引用的东西的生命周期联系起来。甚至与优化相关的原因也可能是一个好主意(因为它允许 [&amp;] lambdas 捕获堆栈帧指针和可选的 this 指针,仅此而已)。
  • @Yakk 这很有趣。感谢您指出。我很高兴我的假设是标准的意图
  • 我现在相信我错了。阅读the accepted answer here
  • @Yakk 答案似乎与您所说的相似,只是根据似乎破坏此代码的措辞是在 C++14 之后添加的,并且应该(希望?)修复在 C++17 发布之前。
  • 是的,它很复杂,但在 C++11 和 C++14 中是安全的。然后在 C++14 之后添加了措辞,并在 C++17 之前修复了导致问题的措辞。问题是修复它的措辞与导致问题的改写不在同一个地方!所以我(以及链接的原始答案)很困惑,并认为这是修复 C++14 中的一个缺陷;实际上,这是在 C++17 最终确定之前修复的 C++17 缺陷。
【解决方案2】:

如图所示,您在声明 x 的块范围内调用 lambda,并且没有悬空引用。

值得注意的是,内部匿名 lambda 直接从最外面的块作用域而不是外部 lambda 捕获对 x 的引用,因为它正在寻找声明。

如果您在该块范围之外传递(副本)您的 lambda 对象,那么您可能会导致悬空引用。

【讨论】:

    【解决方案3】:

    如果您在不使用 lambda 的情况下重写代码,那么我认为很明显没有悬空引用,只是对仍在范围内的变量 x 的引用:

    class Inner {
        int& x;
      public:
        Inner(int &x) : x(x) {}
        void operator()(){
            x = 5;
        }
    };
    
    class Outer {
        int& x;
      public:
        Outer(int &x) : x(x) {}
        Inner operator()(){
            return {x};
        }
    };
    
    int main() {
        int x=0;
        auto outer = Outer{x};
        auto inner = outer();
        inner();
        std::cout << x;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多