Lambda value of variable caught by reference before and after call

I was doing exercise:
Write a lambda that captures a local int variable and
decrements that variable until it reaches 0. Once the variable is 0 additional
calls should no longer decrement the variable. The lambda should return a
bool that indicates whether the captured variable is 0.

and I discovered some weird behavior.

1
2
3
4
5
6
7
8
9
10
  unsigned sample = 3;

  auto lamda = [&sample] () -> bool
	{ return sample ? !(--sample) : !sample; };

 std::cout << sample << " : " << lamda() << " : " << sample << std::endl;
 std::cout << sample << " : " << lamda() << " : " << sample << std::endl;
 std::cout << sample << " : " << lamda() << " : " << sample << std::endl;
 std::cout << sample << " : " << lamda() << " : " << sample << std::endl;


output is:
2 : 0 : 3
1 : 0 : 2
0 : 1 : 1
0 : 1 : 0

Its looks like there are 2 sample variables, why?
Which one is "real"?
If there is only one sample, why its value is larger after decrementation?
Until C++17, stream output expressions evaluate all their arguments in completely arbitrary order. cout << A << B << C; may execute B, then C, then A, then output the results all three. Or it may execute C, then A, then B, then output the results of all three.
In your case, it appears the order was C, then B, then A. So C on line 6 reads from sample (the result of that read is 3). Then B on line 6 executes lambda(), which decrements sample. Then A on line 6 reads from sample (the result of that read is 2). Then all results (2 from the second read, 0 from the lambda, 3 from the first read) are printed.
So here's the general rule:
Do not read and write a thing at the same time in one expression.
Thank you, I will renember that.
Topic archived. No new replies allowed.