判断语句中std::cin隐式转换为bool--重载operator bool()
When we use an istream as a condition, the effect is to test the state of the stream. If the stream is valid—that is, if the stream hasn’t encountered an error—then the test succeeds. An istream becomes invalid when we hit end-of-file orencounter an invalid input, such as reading a value that is not an integer.
while (std::cin >> value)sum += value; // equivalent to sum = sum + valuestd::cout << "Sum is: " << sum << std::endl;
std::cin >> value返回的不是std::cin吗?这是一个输入流对象,怎么可以作为判断条件?记录发生错误的flag,这里并未判断flag,怎么可以直接把cin作为判断条件?
You’re right to wonder about this! Let me explain the mechanism behind how std::cin >> value
can be used as a condition and why it works in this context.
How std::cin >> value
works:
In C++, the >>
operator used with an input stream (std::cin
) behaves in a way that allows the stream itself to be tested in a condition like an if
statement or a while
loop. Let’s break it down step by step:
-
Input Stream (
std::cin
) and its State:std::cin
is an instance ofstd::istream
, which is a class representing input streams. It can be in one of several states, such as:- Good state (
std::ios::good
): No errors, and the stream is ready for input. - Fail state (
std::ios::fail
): Input extraction failed (e.g., when the user enters something that’s not compatible with the expected type). - End-of-file state (
std::ios::eof
): The end of the input has been reached (i.e., no more data to read). - Bad state (
std::ios::bad
): Serious error that typically indicates that something went wrong with the stream itself, such as hardware failure or other I/O errors.
- Good state (
-
std::cin >> value
:- When you use
std::cin >> value
, it tries to extract data from the input stream and store it in the variablevalue
. - If the extraction is successful (i.e., the input matches the expected type and is valid), the stream remains in a good state.
- If there’s an issue with the input (like trying to read a string when you expect an integer), the stream enters the fail state and the
operator>>
will returnfalse
.
- When you use
-
Using the Stream as a Condition:
- The important part is that
std::cin
(as anistream
object) can be evaluated as a boolean in conditions likewhile
orif
. Theoperator bool
forstd::istream
checks the state of the stream and returns:true
if the stream is in a good state (i.e., no errors, and input was successfully extracted).false
if the stream is in a fail state or end-of-file state.
So when you write:
while (std::cin >> value)
It works because the
operator>>
attempts to extract a value and checks whether the stream is in a valid state. If the input is valid, it continues the loop. If the input is invalid (e.g., a type mismatch or reaching EOF), the loop stops. - The important part is that
In your example:
while (std::cin >> value)sum += value; // equivalent to sum = sum + value
std::cout << "Sum is: " << sum << std::endl;
std::cin >> value
is the key part. It tries to read fromstd::cin
into the variablevalue
. If successful, it updatessum
.- The loop will continue as long as
std::cin
is in a good state (i.e., the input is valid and no errors have occurred). - Once the input is invalid or EOF is reached,
std::cin >> value
will returnfalse
, causing the loop to exit.
Why doesn’t it explicitly check the flags?
- Stream flags (like
failbit
,eofbit
,badbit
) are automatically checked when you usestd::cin
in a condition like this.std::cin >> value
implicitly checks the flags and returns a boolean value:true
if the input was successfully read and no errors occurred.false
if an error (fail or EOF) occurred during the input.
So you don’t need to manually check the stream’s flags (failbit
, eofbit
) in this case because the operator>>
already handles it and gives you a boolean result that you can use directly in conditions.
Example:
Let’s say you enter the following inputs:
- Enter
5
, and the loop will continue and add5
tosum
. - Enter
abc
(which is not an integer), causing thefailbit
to be set. The loop will stop here becausestd::cin
will returnfalse
. - Enter
Ctrl+D
orCtrl+Z
(depending on the OS) to reach EOF. This will also cause the stream to fail and the loop to exit.
Summary:
std::cin >> value
does two things: it attempts to extract a value from the stream and it implicitly checks the stream’s state.- When used in a condition like
while (std::cin >> value)
, it evaluates totrue
if the stream is in a good state andfalse
if there’s an error (e.g., fail or EOF). - You don’t need to explicitly check the flags (like
failbit
) yourself becausestd::cin
automatically handles that when you use it as a condition.
operator>> will return false???正常返回的是cin的引用,cin和false完全是两种不同的类型?一个函数怎么可能返回不同的类型?是重载?
You’re absolutely right to question this, and this is a great observation! Indeed, std::cin >> value
doesn’t directly return false
in the sense of a bool
. Instead, it returns std::cin
itself, but it’s implicitly evaluated as a boolean when used in conditional statements like if
or while
. This behavior is due to operator overloading and implicit conversion to a boolean.
Let me explain the details:
The Key: Operator Overloading and Implicit Conversion
The operator>>
for std::istream
doesn’t return a bool
directly; instead, it returns a reference to the input stream object itself (std::cin
), which is an std::istream&
. So, you are correct that std::cin
and false
are different types. However, the mechanism that allows this to work seamlessly in conditions is operator overloading and implicit type conversion.
1. operator>>
and std::istream
std::istream& operator>>(std::istream& in, T& value);
This operator overloads the stream extraction operator (>>
). It takes an input stream and a reference to a variable, reads from the input stream, and stores the value in the variable. The operator returns the stream object itself (the same input stream that was passed in).
2. operator bool()
in std::istream
std::istream
has a conversion operator called operator bool()
that is implicitly called when the stream object is evaluated in a boolean context (like in if
, while
, etc.). This operator checks the state of the stream to determine if it is in a valid state or has encountered an error.
Here’s the basic structure of operator bool()
for std::istream
:
class std::istream {
public:// Conversion operator to bool to check the stream's stateoperator bool() const {return good(); // Returns true if the stream is in a good state, false otherwise}
};
good()
checks if the stream is in a good state (no errors likefailbit
,eofbit
, etc.).- If the stream is valid,
operator bool()
returnstrue
. - If the stream is in a failed state (due to errors like invalid input or reaching EOF),
operator bool()
returnsfalse
.
3. How std::cin >> value
Works in a Condition
- When you use
std::cin >> value
in a condition likewhile (std::cin >> value)
, theoperator>>
returns the stream object (std::cin
) itself. - Then, the conversion operator
operator bool()
is implicitly called onstd::cin
, which evaluates whether the stream is in a good state or has encountered an error (like invalid input or EOF). - Based on this evaluation, the condition is treated as either
true
orfalse
:- If the stream is valid (
good()
istrue
), the condition istrue
, and the loop continues. - If the stream is invalid (due to an error or EOF), the condition is
false
, and the loop stops.
- If the stream is valid (
Simplified Example:
Here’s a simple breakdown:
std::cin >> value; // Calls operator>>if (std::cin) { // Implicitly calls operator bool()// Stream is in good state, proceed
} else {// Stream is in fail state or EOF
}
So, while the operator>>
returns std::cin
(an istream&
), std::cin
itself is implicitly converted to a bool
when used in a condition. This conversion is what makes the check work as intended.
Summary:
operator>>
forstd::istream
returns a reference to the stream itself (std::istream&
), not abool
.std::istream
has a conversion operator (operator bool()
) that allows the stream to be evaluated as a boolean value.- This operator checks the state of the stream (valid or failed) and returns
true
orfalse
accordingly. - This mechanism enables
std::cin >> value
to be used directly in conditions likewhile
orif
to check whether the stream is in a valid state.
This is an example of operator overloading and implicit type conversion working together to make stream handling more convenient and intuitive(直观的).