简体   繁体   中英

Is std::cin >> i >> ++i; undefined behavior

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 .

Case I

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

  1. std::cin::operator>> returns cin object by reference
  2. Each call to std::cin>>operator>> is guaranteed to be made in order from left to right.

So there is no undefined behavior in this case.

Case II

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:

  1. i is evaluated before the first call to operator>> and
  2. ++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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM