C++ if (cin >> x) - 为什么你可以使用那个条件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6791520/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 20:41:19  来源:igfitidea点击:

if (cin >> x) - Why can you use that condition?

c++variablesif-statementcin

提问by Muhsin Ali

I have been using "Accelerated C++" to learn C++ over the summer, and there's a concept which I don't seem to understand properly.

整个夏天我一直在使用“Accelerated C++”来学习 C++,有一个我似乎不太理解的概念。

Why is

为什么是

int x;
if (cin >> x){}

equivalent to

相当于

cin >> x;
if (cin){}

By looking at the code, it seems to me that we're using cin as a variable. But, I thought it was a function. Why can we use cin in this way when it is x that has whatever value we input into our keyboard?

通过查看代码,在我看来,我们正在使用 cin 作为变量。但是,我认为这是一个函数。当 x 具有我们在键盘中输入的任何值时,为什么我们可以以这种方式使用 cin ?

回答by

cinis an object of class istreamthat represents the standard input stream. It corresponds to the cstdiostream stdin. The operator >>overload for streams return a reference to the same stream. The stream itself can be evaluated in a boolean condition to true or false through a conversion operator.

cinistream表示标准输入流的类的对象。它对应于cstdiostdin>>流的运算符重载返回对同一流的引用。流本身可以通过转换运算符在布尔条件中评估为真或假。

cinprovides formatted stream extraction. The operation cin >> x;

cin提供格式化流提取。操作 cin >> x;

where "x" is an int will fail if a non-numeric value is entered. So:

如果输入非数字值,其中 "x" 是 int 将失败。所以:

if(cin>>x)

will return falseif you enter a letter rather than a digit.

false如果您输入字母而不是数字,将返回。

This website on tips and tricks using C++ I/Owill help you too.

这个关于使用 C++ I/O 的提示和技巧的网站也会对您有所帮助。

回答by David Hammen

Note: Answer updated four years after the fact to address both C++98/03 and C++11 (and beyond).

注意:答案在四年后更新,以解决 C++98/03 和 C++11(及更高版本)的问题。



std::cinis an instance of a std::istream. That class provides two overloads that pertain to this question.

std::cin是 a 的一个实例std::istream。该类提供了与此问题相关的两个重载。

  • operator >>reads data from the stream into the target variable if that is possible. If the immediate contents of the stream cannot be translated into the type of the target variable, the stream is instead marked as invalid and the target variable is left untouched. Regardless of the success/failure of the operation, the return value is a reference to the stream.
  • Either operator void*()(pre-C++11), which converts the stream reference to a void*pointer, or explicit operator bool()(C++11), which converts the stream reference to a boolean. The result of this conversion is a non-null pointer (pre-C++11) or true(C++11) if the stream is valid, but the null pointer (pre-C++11) or false(C++11) if the stream isn't valid.
  • operator >>如果可能,从流中读取数据到目标变量中。如果流的直接内容无法转换为目标变量的类型,则该流将被标记为无效,并且目标变量保持不变。无论操作成功/失败,返回值都是对流的引用。
  • 任一operator void*()(预C ++ 11),其将流参照void*指针,或explicit operator bool()(C ++ 11),其将流参考一个布尔值。true如果流有效,则此转换的结果是非空指针 (pre-C++11) 或(C++11),但空指针 (pre-C++11) 或false(C++11) ) 如果流无效。

An ifstatement needs either a boolean, an integer, or a pointer as the quantity to be tested. The result of std::cin >> xis a reference to an istream, which is none of the above. However, the class istreamdoes have those conversion operators which can be used to transform the istreamreference to something usable in an ifstatement. It is the version-specific conversion operator that the language uses for the iftest. Since failure to read marks the stream as invalid, the iftest will fail if the read didn't work.

一条if语句需要一个布尔值、一个整数或一个指针作为要测试的数量。的结果std::cin >> x是对 an 的引用istream,这不是上述任何一个。但是,该类istream确实具有那些可用于将istream引用转换为if语句中可用内容的转换运算符。它是语言用于if测试的特定于版本的转换运算符。由于读取失败将流标记为无效,if如果读取无效,测试将失败。

The reason for the more convoluted operator void*conversion member prior to C++11 is that it wasn't until C++11 that the already existing explicitkeyword was extended to apply to conversion operators as well as constructors. A non-explicit operator bool()would have presented far too many opportunities for programmers to shoot themselves in the foot. There are problems with operator void*()as well. The "safe bool idiom" would have been a fix, but simply extending explicitaccomplished exactly what the safe bool idiom accomplishes, and without having to use a lot of SFINAE magic.

operator void*在 C++11 之前使用更复杂的转换成员的原因是,直到 C++11,已经存在的explicit关键字才被扩展为适用于转换运算符和构造函数。一个非明确的东西operator bool()会给程序员提供太多的机会来射自己的脚。也有问题operator void*()。“safe bool idiom”本来是一个修复,但简单地扩展就explicit完全完成了safe bool idiom 所完成的工作,而不必使用很多SFINAE 魔法。

回答by SLaks

cinis a (global) variable of type istream, not a function.

cin是一个(全局)类型的变量istream,而不是一个函数。

The istreamclass overrides the >>operator to perform input and return a reference to the object you called it on (cin).

istream类覆盖了>>操作者进行输入,并返回到你把它称为对对象的引用(cin)。

回答by Olympian

cinis variable in stdnamespace.

cinstd命名空间中的变量。

operator>>return reference to cin, because of it you can write: cin >> a >> b, instead of cin >> a; cin >> b;

operator>>返回对 的引用cin,因为它你可以写:cin >> a >> b,而不是cin >> a; cin >> b;

回答by Erix

because the result of the expression

因为表达式的结果

cin >> x

evaluates to

评估为

cin

after the stream is read.

读取流后。

回答by Zachary

The answers above are informative. Here I just give an extra comment.

上面的答案是信息性的。在这里,我只做一个额外的评论。

std::cinis an object of class istreamand represents the standard input stream(i.e. the keyboard) which corresponds to stdinin C stream.

std::cin是一个类的对象,istream代表标准输入流(即键盘),它对应stdin于 C

cin >> xwould firstly read an int from the standard input stream and assignment it to x. After that return a self reference to cin. So the return value of function call cin >> xis still cin.

cin >> x将首先从标准输入流中读取一个 int 并将其分配给x. 之后返回对cin. 所以函数调用的返回值cin >> x仍然是cin

So from the point of if condition, if(cin)and if(cin >> x)resemble each other. The standard IO Librarydefines a function for the stream like this (depends on implementation):

所以从if 条件来看,if(cin)if(cin >> x)彼此相似。标准IO 库为这样的流定义了一个函数(取决于实现):

explicit operator bool() const; // C++11

or

或者

operator void*() const; //C++98, C++2003

From this two declarations, we know they castthe stream typedirectly or indirectly(through void*pinter to boolwhich is obvious) to booltype.

从这两个声明,我们知道他们流类型直接或间接(通过void*品特到bool这是显而易见的)来bool输入。

Within this two functions, they depends on some basic IO steamstatuses(class fields) to determine whether return false or true (for void*case, it is nullptror not).

在这两个函数中,它们依赖于一些基本的IO 流状态(类字段)来确定是否返回 false 或 true(void*例如,是否nullptr)。

cinis an instance of class istreamwhich inherits the casting-to-boolfunction. So it works!

cin是一个类的实例,istream它继承了cast-to-bool函数。所以它有效!

回答by Ryan Le

1) cinis an instance of istream, see http://www.cplusplus.com/reference/iostream/cin/.

1)cin是 的一个实例istream,参见http://www.cplusplus.com/reference/iostream/cin/

2) the >>operator of istreamwill return its left operand, in this case it is cin, see http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/. This operator will set failbiton if no characters were extracted from the cin, in case the reader has finished EOFso there will be no more character to read.

2) 的>>运算符istream将返回其左操作数,在本例中为cin,请参见http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/failbit如果没有从 中提取字符,则此运算符将设置为on cin,以防读取器已完成,EOF因此将不再有字符可读取。

3) As of the 2) above, when the condition is evaluated after the reading operation, if (cin >> x)should be like if (cin), refer to this link http://www.cplusplus.com/reference/ios/ios/operator_bool/you will see that, this ifblock will return:

3)如上面的2),当读取操作后评估条件时,if (cin >> x)应该是这样的if (cin),参考这个链接http://www.cplusplus.com/reference/ios/ios/operator_bool/你会看到,此if块将返回:

  • A null pointer if at least one of failbitor badbitis set. Some other value otherwise (for C++98 standard).

  • The function returns false if at least one of these error flags is set, and true otherwise. (for C++11 standard)

  • 如果至少设置了failbit或之一,badbit则为空指针。其他一些值(对于 C++98 标准)。

  • 如果至少设置了这些错误标志之一,则该函数返回 false,否则返回 true。(对于 C++11 标准)

回答by Alan Birtles

std::cinis an instance of the std::istreamclass.

std::cinstd::istream类的一个实例。

cin >> xis just calling a function on the cinobject. You can call the function directly:

cin >> x只是在cin对象上调用一个函数。您可以直接调用该函数:

cin.operator >>(x);

To allow you to read multiple variables at once the operator >>function returns a reference to the stream it was called on. You can call:

为了允许您一次读取多个变量,该operator >>函数返回对其调用的流的引用。您可以致电:

cin >> x >> y;

or equivalently:

或等效地:

cin.operator >>(x).operator >>(y);

or:

或者:

std::istream& stream = cin.operator >>(x);
stream.operator >>(y);

The final part of the puzzle is that std::istreamis convertibleto bool. The bool is equivalent to calling !fail().

拼图的最后一部分是std::istream可以转换bool. bool 相当于调用!fail().

So in the following code:

所以在下面的代码中:

int x;
std::istream& stream = std::cin.operator >>(x);
bool readOK = !stream.fail();
if (readOK)
{
  std::cout << x << "\n";
}

bool readOK = !stream.fail();can be reduced to just bool readOK = stream;.

bool readOK = !stream.fail();可以减少到刚刚bool readOK = stream;

You don't need a separate boolto store the stream state so can just do if (stream).

您不需要单独的bool来存储流状态,所以可以只做if (stream).

Removing the temporary streamvariable gives if (std::cin.operator >>(x)).

删除临时stream变量给出if (std::cin.operator >>(x)).

Using the operator directly gets us back to the original code:

直接使用运算符让我们回到原来的代码:

int x;
if (std::cin >> x)
{
  std::cout << x << "\n";
}

回答by Emil Condrea

because cin is an object of class, read more on http://www.cplusplus.com/reference/iostream/cin/.

因为 cin 是类的对象,请在http://www.cplusplus.com/reference/iostream/cin/上阅读更多内容。