Various results obtained using common signs of lambda and automatic return in C ++ 14

I am trying to implement this piece of a high order function in python using C ++:

def add1(x): def helper(): nonlocal x x += 1 return x return helper 

Here are three versions I created:

 #include <iostream> #include <functional> using namespace std; function<int(void)> add1_v1(int x) { function<int(void)> g = [&x]() {return ++x;}; return g; } auto add1_v2(int x) { function<int(void)> g = [&x]() {return ++x;}; return g; } auto add1_v3(int x) { auto g = [&x]() {return ++x;}; return g; } int main() { auto a = add1_v1(100); auto b = add1_v2(100); auto c = add1_v3(100); for(int i = 0; i < 3; ++i) { cout << a() << endl; } cout << "-------------------------------------------" << endl; for(int i = 0; i < 3; ++i) { cout << b() << endl; } cout << "-------------------------------------------" << endl; for(int i = 0; i < 3; ++i) { cout << c() << endl; } return 0; } 

Outputs:

 101 102 103 ------------------------------------------- 4239465 4239466 4239467 ------------------------------------------- 4201325 4201325 4201325 

Only add1_v1 matches what I want. Can someone explain the reason to me?

+5
source share
3 answers

The reason is that this behavior is undefined.

Inner lambda captures x by reference.

The problem is that as soon as add() returns, its parameter is destroyed, and the returned lambda has a sagging reference to the destroyed object.

Lambda should fix x by value; and what it seems to me that you are really trying to do here is mutable lambda :

 auto add(int x) { function<int(void)> g = [x]() mutable {return ++x;}; return g; } 

Note that this approach has certain implications when it comes to subsequent copying of the returned lambda; but as long as the returned lambda stays β€œin one place”, for the rest of your life, the resulting semantics will probably be what you expect.

+7
source

They are all poorly formed, because you capture x by reference in lambda, but x is a local variable and will be destroyed when you exit the add function, then the link will hang out, play the last one on it, calls UB, which means that everything is possible; even the first case seems beautiful.

+4
source

Not an answer, it seems that the whole version of the functions works well if you change the parameter signature to add1_v * (int && x)

0
source

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


All Articles