I am trying to understand the order of evaluation of expressions in C++. I have the following examples:
int i = 0;
std::cin >> i >> i; //IS THIS UB?
My first question is that does the above shown snippet produces UB?
Next,
int i = 0;
std::cin >> i >> ++i; //IS THIS UB?
My second question is that does this snippet produces UB?
std::cin >> i >> i;
is and always was well-defined.
std::cin >> i >> ++i;
is well-defined now, but was UB pre-C++17.
This kind of UB is caused either by unsequenced writes to the same scalar, or a write unsequenced relative to a read of the same scalar.
In std::cin >> i >> i;
, even though i
is modified twice (inside of the overloaded >>
), the first modification is sequenced before the second one. The return value of the first >>
has to be calculated first, to be passed as an argument to the second >>
, so they have to be called in this order. See rule (3) here .
In std::cin >> i >> ++i;
, on the other hand, pre-C++17 there was an unsequenced write ( ++i
) relative to a read ( i
), causing UB. But in C++17 and newer, >>
and <<
always compute the lhs before rhs, causing i
to be sequenced before ++i
, see rule (19) here .
In this case, std::cin >> i >> i;
can be written as(or equivalent to):
std::cin.operator>>(i).operator>>(i);
There are 2 important things to consider here
std::cin::operator>>
returns cin
object by reference std::cin>>operator>>
is guaranteed to be made in order from left to right.So there is no undefined behavior in this case.
In this case, std::cin >> i >> ++i;
can be written as(or equivalent to):
std::cin.operator>>(i).operator>>(++i);
Now, from Section 1.9, Point 16 :
When calling a function (whether or not the function is inline), there is a sequence point after the evaluation of all function arguments (if any) which takes place before execution of any expressions or statements in the function body. There is also a sequence point after the copying of a returned value and before the execution of any expressions outside the function.
But note that the above quote statement only guarantees that:
i
is evaluated before the first call to operator>>
and ++i
is evaluated before the second call to operator>>
. But the quote doesn't guarantee that i
is evaluated before ++i
or vice versa. This means that the order in which i
and ++i
are evaluated is undefined and so the resulting code in this case will have undefined behavior .
The above discussion is for Pre-C++11 since OP didn't tag C++11.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.