C ++ lambda lexical closure in local variables

Summary

In C ++, when I return a lambda from a function that captures a local variable for that function, what exactly happens and why? The compiler (g ++) seems to resolve it, but it gives me different results than I expected, so I'm not sure if this is technically safe / supported.

More details

In some languages ​​(Swift, Lisp, etc.) you can capture local variables in closure / lambda, and they remain valid in scope as long as closure is in scope (I heard lambda over let over lambda "in the context of Lisp.) For example, in Swift, the sample code for what I'm trying to do is:

func counter(initial: Int) -> (() -> Int) {
    var count = initial
    return { count += 1; return count }
}

let c = counter(initial: 0)
c() // returns 1
c() // returns 2
c() // returns 3

I tried to write the C ++ equivalent as shown below:

auto counter(int initial)
{
    int count = initial;
    return [&count] () -> int {
        count = count + 1;
        return count;
    };
}

However, I get the result:

auto c = counter(0);
std::cout << c() << std::endl; // prints 1
std::cout << c() << std::endl; // prints 1
std::cout << c() << std::endl; // prints 1

, , , . , :

int count = 0;
auto c = [&count] () -> int {
    count = count + 1;
    return count;
};
std::cout << c() << std::endl; // prints 1
std::cout << c() << std::endl; // prints 2
std::cout << c() << std::endl; // prints 3

, , , ++, ? , ?

+4
3
    return [&count] () -> int {

. .

, , count, , , , count , , . undefined.

, , :

    return [count] () -> int {

, . . :

 return [count] () mutable -> int
 {
    return ++count;
 };

" " , - , , , , , . :

class SomeAnonymousClassName {

     int &count;

public:
     SomeAnonymousClassName(int &count) : count(count)
     {}

     int operator()
     {
          // Whatever you stick in your lambda goes here.
     }
};

- , . - , , - , . - operator().

operator() const. operator() -t28 > , .

+8

, , undefined - . , .

initail :

auto counter(int &count)
{
    return [&count] () -> int {
        count = count + 1;
        return count;
    };
}

int main()
{
    int initial = 0;
    auto c = counter(initial);
    std::cout << c() << std::endl; // prints 1
    std::cout << c() << std::endl; // prints 2
    std::cout << c() << std::endl; // prints 3
}
0

In the first case, you commit a link to a local variable. The link is returned when the function returns. Therefore, your program is subject to undefined action.

0
source

Source: https://habr.com/ru/post/1664882/


All Articles