std::cin 如何同时返回布尔值和自身

How can std::cin return a bool and itself at the same time?

本文关键字:布尔值 何同时 cin std 返回      更新时间:2023-10-16

我正在读一本关于C++的书,里面说如果我使用>> 运算符,它会返回运算符左侧的对象,所以在这个例子中

std::cin >> value1;

代码返回 std::cin

但如果我这样做

while(std::cin >> value1)

我的代码将处于循环中,直到出现std::cin错误,因此这必须意味着运算符返回一个bool,当std::cin不失败时为 true,在std::cin失败时返回 false。

是哪一个?

[...]所以这必须意味着运算符返回一个布尔值[...]

不,它返回std::cin(通过引用(。while(std::cin >> value);之所以有效,是因为std::istream(std::cin的类型(有一个转换运算符

转换运算符基本上允许将类隐式(如果它没有标记为explicit(转换为给定类型。在这种情况下,std::istream定义其operator bool以返回是否发生了错误(通常failbit(;

[std::ios_base::operator bool()]

如果流没有错误并且已准备好执行 I/O 操作,则返回true。具体来说,返回!fail() .


explicit operator bool() const;

请注意,即使运算符是explicit的(这不应该允许像if (std::cin);这样的隐式转换(,在需要bool的上下文中使用限定符时,限定符会被忽略,如ifwhile循环和for循环。不过,这些都是例外,而不是规则。

下面是一个示例:

if (std::cin >> value);  //OK, a 'std::istream' can be converted into a 'bool', which 
                         //therefore happens implicitly, without the need to cast it: 
if (static_cast<bool>(std::cin >> value)); //Unnecessary
bool b = std::cin >> value;  //Error!! 'operator bool' is marked explicit (see above), so 
                             //we have to call it explicitly:
bool b = static_cast<bool>(std::cin >> value); //OK, 'operator bool' is called explicitly

std::istream(std::cin作为对象的类(具有以下成员函数:

explicit operator bool() const;

如果对象处于错误状态,则返回 false,否则返回 true。这就是while(std::cin >> value1)构造起作用的原因。在 C++11 之前,它有这个非显式函数:

operator void*() const;

如果对象处于错误状态,则返回空指针,达到相同的目的。

> std::cin 属于 std::istream 类型(这只是 std::basic_istream<char>typedef(

如果您看到 basic_istream 的不同重载operator>>,则它们都返回对 basic_istream 的引用。所以有一件事需要澄清,这里的operator>>不返回bool而是返回"std::cin"本身。您不会看到任何返回bool值的operator>>

所以现在的问题是,它如何将std::basic_istream转换为bool
答案是:为此目的调用转换运算符

std::basic_istream从其父std::basic_ios继承operator bool()

explicit operator bool() const;

这使得可以将std::basic_istream对象转换为 bool .人们很容易怀疑它被标记为explicit(参见为什么它被标记为explicit(,并且仍然在ifwhile中隐式转换为bool

这个问题的答案是ifwhile"隐式"使用显式转换。(见@R. Martinho Fernandes的回答(。所以ifwhilefor是这种"对bool"内在转换"隐含发生的地方之一。

对流的操作返回对流的引用。

所以,不是bool.

您可以将结果粘贴到if条件中,原因与执行此操作的原因相同:

void* ptr = foo();
if (ptr) { /*...*/ }

而且,就此而言,这个:

int x = foo();
if (x) { /*...*/ }

这里的ptrx都可以转换为bool以在该条件下使用。在std::cin的情况下,转换是通过std::ostream类中的operator bool()来实现的,该是为此任务明确添加的(双关语(。