5

Dear stackoverflow community!

Recently, I was hunting for a bug at work, which led me to the following piece of code I wrote myself. Here is a simplified version:

int main()
{
    for(int i = 0; i < 5; ++i)
    {
        int j = i + 1;

        auto k = [j](){
            static int s{j};
            cout << s << endl;
        };
        k();
    }
}

I know that it might look silly, but there was some logic behind it (since I was using this lambda to connect to a slot in QT framework)

Here are my expectations:

  1. each iteration of the loop new class with a functor operator will be created (since every time it captures new local variable)
  2. initialization of static variable s will happen once every iteration since it is a different lambda

However, I was wrong. After compiling with GCC 9.3.0 I got the following output:

1
1
1
1
1

Does it mean that 1 "hidden" functor is created once for every iteration of the loop (then a static is initialized during the first iteration of the loop)? Does it then mean that we should avoid nasty non-constexpr static variables in lambdas? Where am I wrong?

Thanks for you time, looking forward to any replies.

1 Answer 1

7

Think of a lambda expression as a terse recipe to define a class that overloads the call operator(). In your case:

struct LambdaEquivalent {
    int j;

    auto operator() const
    {
        static int s{j};
        cout << s << endl;
    }
};

And you loop then is

for(int i = 0; i < 5; ++i)
{
        int j = i + 1;
        LambdaEquivalent k{j};
        k()
}

This illustrates that any local static data in the body of a lambda expression is nothing but local static data in a member function - and that is initialized exactly once. It's a good thing that both cases behave identically, handling it differently could be very confusing.

Sign up to request clarification or add additional context in comments.

2 Comments

Aha, now I got it, thanks. I guess it just boils down to a static function member, which is initialized based on the value of the function argument during its first call.
cppinsights.io can help you translating a lot of features back to C++98 code and can generate this kind of insight

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.