58

整个夏天我一直在使用“加速 C++”来学习 C++,并且有一个我似乎没有正确理解的概念。

为什么是

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

相当于

cin >> x;
if (cin){}

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

4

9 回答 9

72

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

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

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

if(cin>>x)

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

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

于 2011-07-22T14:31:37.993 回答
39

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


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

  • operator >>如果可能,将数据从流中读取到目标变量中。如果流的直接内容不能转换为目标变量的类型,则流被标记为无效并且目标变量保持不变。无论操作成功/失败,返回值都是对流的引用。
  • operator void*()将流引用转换为指针的(C++11 之前的)void*explicit operator bool()将流引用转换为布尔值的(C++11)。true如果流有效,则此转换的结果是非空指针 (pre-C++11) 或(C++11),但空指针 (pre-C++11) 或false(C++11 ) 如果流无效。

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

在 C++11 之前使用更复杂的转换成员的原因operator void*是,直到 C++11 才将已经存在的explicit关键字扩展为适用于转换运算符和构造函数。一个非显式的operator bool()代码会给程序员提供太多的机会让他们自爆。也有问题operator void*()。“安全布尔成语”本来可以解决问题,但只需扩展即可explicit完成安全布尔成语所完成的工作,而无需使用大量 SFINAE 魔法。

于 2011-07-22T14:55:24.493 回答
7

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

该类istream覆盖>>操作符以执行输入并返回对您调用它的对象的引用 ( cin)。

于 2011-07-22T14:32:02.710 回答
7

cin在命名空间中是变量std

operator>>返回对 的引用cin,因此您可以编写: cin >> a >> b,而不是cin >> a; cin >> b;

于 2011-07-22T14:32:31.040 回答
6

上面的答案是有益的。在这里,我只是提供一个额外的评论。

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

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

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

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

或者

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

从这两个声明中,我们知道它们直接或间接地(通过pinter很明显)将类型转换为类型。void*boolbool

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

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

于 2013-06-21T10:29:58.273 回答
5

因为表达式的结果

cin >> x

评估为

cin

在读取流之后。

于 2011-07-22T14:33:22.440 回答
1

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

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

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

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

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

于 2015-04-17T06:37:53.293 回答
1

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

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

cin.operator >>(x);

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

cin >> x >> y;

或等效地:

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

或者:

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

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

所以在下面的代码中:

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

bool readOK = !stream.fail();可以归结为刚刚bool readOK = stream;

您不需要单独bool存储流状态,因此可以这样做if (stream)

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

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

int x;
if (std::cin >> x)
{
  std::cout << x << "\n";
}
于 2020-02-07T08:37:05.523 回答
0

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

于 2011-07-22T14:31:53.140 回答