std::cout prints old value

If I call a function, that changes value of a variable, in std::cout and try to print that value then std::cout prints old value.

1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
int reset(int& v)
{
   v = 0;
   return 0;
}
int main()
{
   int i = 5;
   std::cout << reset(i) << " " << i; //output: 0 5
}


Expected output: 0 0
Last edited on
You are probably in the realm of "undefined behaviour", or possibly "depends which version of the standard" behaviour. I should avoid making changes to a variable in the midst of a complex output statement.

My compiler gives
0 0
to your original code, but cpp.sh gives
0 5
Neither give any warnings.


If your reset function changes v via a reference argument it might be better as a void function, although obviously you couldn't then put it in an output statement.


For safety's sake ...

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
int reset(int& v)
{
   v = 0;
   return 0;    // <==== did you mean    return v;
}
int main()
{
   int i = 5;
   std::cout << reset(i);
   std::cout << " " << i;    // <==== Use a separate statement
}

In cpp.sh:
0 0 
Last edited on
Actually it is not undefined behavior. The result depends on the order of evaluation.

So in your case i is evaluated first and after that reset(...) is called. This might not be the expected output but perfectly fine.
coder777 wrote:
it is not undefined behavior


But consider the OP's original code (reproduced below) and run on the SAME online system - Rextester - with two of that system's compilers:
gcc ( https://rextester.com/l/cpp_online_compiler_gcc ) produces
0 5

clang ( https://rextester.com/l/cpp_online_compiler_clang ) produces
0 0

If it produces two different results then I would regard the result as "unreliable", if not "undefined".

For reference (in case it gets edited) the OP's code for test:
1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
int reset(int& v)
{
   v = 0;
   return 0;
}
int main()
{
   int i = 5;
   std::cout << reset(i) << " " << i; //output: 0 5
}

The word is unspecified. See:

https://en.cppreference.com/w/cpp/language/eval_order

Therefore you shouldn't modify a value while it is evaluated. If you don't do that you will get the expected output:
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
int reset(int& v)
{
   v = 0;
   return 0;
}
int main()
{
   int i = 5;
   int j = reset(i); // Note
   std::cout << j << " " << i; //output: 0 0
}
Yes, separating the evaluation of reset(i) and the output of i into two separate statements is what I did in my first reply to the OP (albeit with two output statements, rather than an intermediate variable).

So we now have a fine distinction between:
- undefined
- unspecified

Ah, the semantics of the C++ language! Perhaps it is unspecified what the compiler will do with undefined behaviour. .... Or is that the other way round?

Thank-you, anyway, coder777.

Last edited on
The way I understand it in practical terms, unspecified means that if you select from a finite list of possible outcomes, it will be one of those outcomes (hopefully, compiler documentation can tell you what that outcome is).
But undefined means anything could happen, especially when optimizations are turned on. So when the standard changed this behavior from undefined to unspecified, it prevents the optimizer from completely blowing apart your program, but it still might not do what you want.
Best to just avoid any of this "behavior".
Last edited on
implementation defined-behaviour:
behavior, for a well-formed program construct and correct data, that depends on the implementation and that each implementation documents.
https://eel.is/c++draft/intro.defs#defns.impl.defined

unspecified behaviour:
behavior, for a well-formed program construct and correct data, that depends on the implementation.
[Note: The implementation is not required to document which behavior occurs.]
https://eel.is/c++draft/intro.defs#defns.unspecified


In current C++ (C++17), the behaviour of the program is well-defined;
one would get the output that Ricoxor expects.
19) In a shift operator expression E1<<E2 and E1>>E2, every value computation and side-effect of E1 is sequenced before every value computation and side effect of E2 (since C++17)
https://en.cppreference.com/w/cpp/language/eval_order
Interesting, I didn't know there was a specific rule for bitshift/stream operator, thanks.

[Note: The implementation is not required to document which behavior occurs.]
:( nevermind then
Last edited on
So, prior to C++17 the behaviour was "unspecified" (and the implementation wasn't obliged to give you a clue as to which behaviour would occur).

Post C++17 the behaviour is "well-defined" (and will give 0 0 here).

So, in 2019 we are operating in ... oh, don't go down there!
Topic archived. No new replies allowed.