I have a lambda inside a for loop with the loop variable parameter in the lambda. When I run it, I expect the numbers 0-9 to be output. But since it is a lambda, the x doesn’t get evaluated immediately.
for (int x = 0; x < n; ++x)
{
vec.push_back(thread{[&x]() {
m.lock();
cout << x << endl;
m.unlock();
}});
}
Output:
0
3
3
9
etc.
The solution for other languages would be to create a temporary variable,
for (int x = 0; x < n; ++x)
{
int tmp = x;
vec.push_back(thread{[&tmp]() {
m.lock();
cout << tmp << endl;
m.unlock();
}});
}
but that doesn’t seem to work.
see Threads receiving wrong parameters
Bonus:
In my search for an answer, I stumbled upon this question
Generalizing C++11 Threads class to work with lambda
which recommends not using a container that would invalidate the iterators.
Why would that be?
When you specify the capture, you can choose between capture by value and capture by reference. You have chosen to capture by reference. Capturing by reference means that the variable inside the lambda function is referring to the same object. The implication is that any changes to this variable will be shared and you also need to make sure that the referenced object stays around for the life-time of the lambda function.
You probably meant to capture by values. To do this, you can either replace the capture specification to become
[=]or to become[x]. The latter makes sure that onlyxcan be accessed while the former would allow other variables to be accessible.BTW, I’d recommend not using
lock()andunlock()explicitly but rather use one of the lock guards. With this, the body of your loop would look something like this: