Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Understanding capture by reference in C++ lamdba functions

I thought I understood how capture by reference works in C++ until I faced this situation:

auto inrcrementer = []() {
    int counter = 0;
    return [&counter]() {
        return counter++;
    };
};

int main() {
    auto inc = inrcrementer();
    cout << inc() << ", " << inc() << ", " << inc() << ", " << endl;

    return 0;
}

I was expecting this to return 0, 1, 2 but it returns 0, 32765, 32765. Why?

Moreover, if I change it to this:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

auto inrcrementer = []() {
    int counter = 0;
    return [counter]() mutable {
        return counter++;
    };
};

int main() {
    auto inc = inrcrementer();
    cout << inc() << ", " << inc() << ", " << inc() << ", " << endl;

    return 0;
}

It is fixed and it returns as expected. What is the difference between the two?

>Solution :

The problem is that in your first example, the lambda stores a reference to, rather than a copy of, counter. But counter goes out of scope when incrementer returns so that reference is left dangling. Then, when you invoke the lambda returned by incrementer, that reference is invalid.

What this usually means in practise is that it is pointing at an area of the stack that has been / is being used for something else. That’s why you get weird results.

In your second example, the lambda has its own copy of counter, and that remains in scope for as long as the lambda remains in existence. Since you have declared the lambda mutable, it can do whatever it likes with its (private) copy of counter without anybody else messing with it.

So capture by reference can be dangerous. Use with care! A reference is just a pointer really, under the skin, but because it doesn’t look like one it’s easy to slip up.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading