Subhash Jha
Subhash Jha

Reputation: 64

Changing the values of captured variables inside the c++ lambda

I am trying to increment a captured variable to a lambda function by reference but unable to do so.

By capturing the variable by value and then making the lambda mutable, I am able to increment the value. But by passing the reference, the increment is not getting applied.

Also, In case of capture by value, how the value is getting updated across the calls to inc(). Is this similar to closure in JS?

**Capture By reference**

auto inc_count(int x){
    return [&x](){
        return x++;
    };
};

int main()
{
    auto inc = inc_count(4);
    cout<<inc()<<endl;    //32765
    cout<<inc()<<endl;    //32765
    cout<<inc()<<endl;    //32765
    cout<<inc()<<endl;    //32765

    return 0;
}


**Capture by value**

auto inc_count(int x){
    return [x]()mutable{
        return x++;
    };
};

int main()
{
    auto inc = inc_count(4);
    cout<<inc()<<endl;     //4
    cout<<inc()<<endl;     //5
    cout<<inc()<<endl;     //6
    cout<<inc()<<endl;     //7

    return 0;
}

Actual Output :
32765
32765
32765
32765

Expected Output :
4
5
6
7

Upvotes: 1

Views: 2005

Answers (2)

alteredinstance
alteredinstance

Reputation: 597

In this function, you receive x as a copy of some argument.

auto inc_count(int x){
    return [&x](){
        return x++;
    };
};

When you return from inc_count, the x being referenced by your returned value, &x, is destroyed. This is why your value is close to the maximum short value, 32,767. The memory at the address you are attempting to access has been freed and no longer contains any data structure.

Your pass by value works because the memory is not being freed. You are passing a copy of your data at each point; the program is not freeing this data and you end up with a coherent value.

Upvotes: 0

R Sahu
R Sahu

Reputation: 206567

In the first version, you are capturing a reference to a variable that is not alive after the function returns. You have a dangling reference after the function returns and your code has undefined behavior.

You can use the following to capture by reference.

auto inc_count(int& x){
    return [&x](){
        return x++;
    };
};

But then, you can't use int_count(4) in main. You'll have to use a variable whose reference can be used in int_count.

int main()
{
    int number = 4;
    auto inc = inc_count(number);

    ...

    return 0;
}

Upvotes: 6

Related Questions