3

below is my practice code about c++11 lambda:

#include<iostream>
int d = 0;
int main()
{
    int e = 1;
    auto i = [&]() ->int {
        e += 1;
        d += 1;
        return d;};

    d += 1;
    std::cout << "the value of d:" << d <<  std::endl;
    std::cout << "the value of i():" << i() << std::endl << " e:" << e << " d:"  << d << std::endl;
    std::cout << " e:" << e << " d:" << d << std::endl;
    return 0; 
}

and i got result not as expected:

the value of d:1
the value of i():2
e:1 d:1
e:2 d:2

I just don't understand why

 std::cout << "the value of i():" << i() << std::endl << " e:" << e << " d:"  << d << std::endl;
 std::cout << " e:" << e << " d:" << d << std::endl;

this two lines give different out put of e and d?

ps:forgive my bad english

wilson
  • 71
  • 3
  • 1
    This is the same undefined behaviour as `std::cout << i++ << i++` – Csq Jun 06 '14 at 10:49
  • 1
    You should read: http://stackoverflow.com/questions/4176328/undefined-behavior-and-sequence-points – Csq Jun 06 '14 at 10:51
  • @Csq It is true that the order of the evaluations is unspecified, but this isn't undefined behavior. There are no unsequenced modifications to the same object in this program. – Casey Jun 06 '14 at 20:08
  • @Casey The OP is modifying `e` and printing it in the same sequence point when writing `(...) i() << std::endl << " e:" << e (...)`. Why is it not undefined behaviour? – Csq Jun 06 '14 at 20:39
  • @Csq `i()` is a function call: the modification in `i` is therefore sequenced *after* everything that occurs before the call to `i` and *before* everything that occurs after `i` returns. The ordering of the evaluation of the expressions `i()` and `e` is unspecified, but not unsequenced. – Casey Jun 08 '14 at 00:53

2 Answers2

1

The order of evaluation of function arguments is unspecified. So function arguments can be evaluated right to left or left to right. It seems that your compiler evaluates arguments from right to left. So in this statement

std::cout << "the value of i():" << i() << std::endl << " e:" << e << " d:"  << d << << std::endl;

the compiler at first evaluates d that is equal to 1 then e that is equal also to 1 and only after that it evaluates i() that returns 2. So you get the following output

the value of i():2
e:1 d:1

Take into account that in this statement using of operator << is equivalent to a call of an appropriate overloaded operator function with the corresponding arguments.

For example this code snippet

int a = 10, b = 20;

std::cout << a << ' ' << b;

is equivalent to

int a = 10, b = 20;

std::operator <<( std::cout.operator <<( a ),  ' ' ).operator <<( b );

To get the expected result you should split the original statement into

std::cout << "the value of i():" << i() << std::endl 
std::cout << " e:" << e << " d:"  << d << << std::endl;
Vlad from Moscow
  • 224,104
  • 15
  • 141
  • 268
1

The evaluation order of the operands of << isn't specified; so it's unspecified whether the values of e and d in the first line are taken before or after they're incremented by the call to i().

So you might get the values before or after they're incremented, depending on the whim of the compiler.

The second line is sequenced after the first, so you'll definitely get the incremented values there.

Mike Seymour
  • 235,407
  • 25
  • 414
  • 617