Both answers are bad answers but only first one may exhibit undefined behavior.
int old = (std::cin >> old, old);
When std::cin >> old
fails then old
can have its value that it had. So it can remain as uninitialized int
and so reading from it is undefined behavior.
while (cin >> str, str != "STOP") {
//process str
}
When cin >> str
fails then str
has its previous value. Assuming str
is std::string
it can not have had uninitialized state unlike aggregate types. So it will have its previous value for example default-constructed value ""
or previously read value "MOP"
. Reading from it and comparing with "STOP"
is never undefined behavior. However it is very likely that cin >> str
will fail next cycle again and so str will never be "STOP"
and so it will be endless loop and so &&
is likely better than comma there.
Also it is worth to note that we can get real crash when we try to combine first example and second example:
std::string old = (std::cin >> old, old);
When streams are not set to throw on failures then we should check state of those manually (and std::cin
is not special) since those may end and fail. Unfortunately lot of tutorial examples do not do it. Therefore some people seem to think that the stream operations are suitable for inserting into middle of some expression using comma operator.
Edit:
I am unsure about comment that it is different from C++11. Did dig, but couldn't find confirmation in standard. Trying this code with g++ did not read zero on case of error:
#include <iostream>
#include <sstream>
int main()
{
std::stringstream in("42");
int i = 0;
std::cout << i << '\n'; // outputs 0
in >> i;
std::cout << i << '\n'; // outputs 42
i = 666;
in >> i;
std::cout << i << '\n'; // outputs 666
// so it did leave value of i like it was
}
Demo. Also std::cin does not seem special in any way. Of course it may be that the implementation of g++ is incorrect or that the failed input is required to set the i
only on case of subset of failures and so the first example still may exhibit undefined behavior.