0

To my surprise, the following C++ program:

#include <iostream>
#include <functional>


int main() {
    std::function<void(void)> f;
    {
        int x = 1;
        f = [&x]() { std::cout << x; };
    }
    //std::cout << x;  // error: use of undeclared identifier 'x'
    f();               // no error!
    return 0;
}

outputs:

1

I would have expected the same output as the output that I get when uncommenting the commented line:

error: use of undeclared identifier 'x'

since the lambda f captured the automatic variable x by reference (not by value) and x is not in context at the point of call f() (so x in f body is a dangling reference).

Why does lambda capture by reference is still working with dangling references?

Géry Ogam
  • 6,336
  • 4
  • 38
  • 67
  • 1
    That's undefined behavior, you're just lucky that you got the output you did, and it appears to be working, different compiler/different optimizations or compiler flags can break it. – Kaldrr Aug 11 '20 at 10:42
  • Why do dangling references work when there *aren't* any lambdas? – user253751 Aug 11 '20 at 11:09

2 Answers2

1

It is not working. This is just a coincidence that it showed 1. Just something that by the time the lambda is called resides at the captured address holds the value that can be interpreted as type int with value 1.

Lifetime of the lambda is greater than lifetime of the variable. Variable x gets destroyed at the closing curly bracket, but lambda still holds reference to it. Any attempts to access that reference result in undefined behavior.

In lambda declaration you tell what to capture. The current scope of the place where it is declared is used. While invoking the lambda you tell when to capture. That is why it compiles compared to references in your question. But it is your responsibility to provide correct lifetimes of the variables used.

Vasilij
  • 1,861
  • 1
  • 5
  • 9
1

Why does lambda capture by reference is still working with dangling references?

This is undefined behaviour so there can be any reason for why it is working the way it is working. If you compile the code with:

Try here: https://godbolt.org/z/5dd5sM

clang++ -O3 -fsanitize=address

You will immediately get:

ERROR: AddressSanitizer: stack-use-after-scope on address ....
READ of size 4...
Waqar
  • 8,558
  • 4
  • 35
  • 43