关于表达式返回值类型的菜鸟问题
最近在看<C++ Primer Fourth Edition>学习c++,第1.4.4节有个例子如下:
#include <iostream>
int main()
{
int sum = 0, value;
// read till end-of-file, calculating a running total of all values read
while (std::cin >> value)
sum += value; // equivalent to sum = sum + value
std::cout << "Sum is: " << sum << std::endl;
return 0;
}
其中while (std::cin >> value)让我很不解,语句std::cin >> value只是用来输入数据并赋值给value变量,为何可以作为逻辑表达式??运行时发现除非输入英文字母,否则一律为真,就连输入enter也为真.请问std::cin >> value表达式的值是怎么定义的??
问题点数:20、回复次数:7Top
1 楼LoveVV99(LoveVV)回复于 2006-06-01 12:35:09 得分 0
输入数字才会是true,除了数字之外的任何输入都会false从而跳出循环,楼主搞错了吧?
while()中的判断条件应该是value,输入不是数字时由于value=0所以跳出了。
Top
2 楼LoveVV99(LoveVV)回复于 2006-06-01 12:41:20 得分 0
错了,cin返回的是istream,并且在出现错误或结束时返回false,所以当你输入的数据不能转换为整数时,就false跳出循环了。Top
3 楼LoveVV99(LoveVV)回复于 2006-06-01 12:47:12 得分 15
(std::cin>>foo)表达式调用了适当的operator>>(例如,它调用了左边带有std::istream参数以及,如果的类型是int,并且右边有一个int&的operator>>)。std::istream operator>>函数按惯例地返回左边的参数,在这里,它返回std::cin。下一步编译器注意到返回的 std::istream处于一个布尔型的上下文中,因此编译器将std::istream转换为一个布尔值。
编译器调用一个称为std::istream::operatorvoid*()的成员函数来将std::istream转换成布尔。它返回一个被转换成布尔的void*指针(NULL成为false,任何其他的指针成为true)。因此在这里,编译器产生了std::cin.operatorvoid*()的调用,就如同你象(void*)std::cin这样显式地强制类型转换。
如果stream处于良好状态,那么转换算符operatorvoid*()返回非指针,如果处于失败状态,则返回 NULL。例如,如果读了太多次(也就是说,已经处于end-of-file),或实际输入到流的信息不是foo的合法类型(如,如果 foo是一个int,而数据是一个“x”字符),流会进入失败状态并且转换算符会返回NULL。
operator>>不是简单地返回一个bool(或 void*)以支出是否成功或失败的原因是为了支持“级联”语法:
std::cin>>foo>>bar;
operator>>是向左结合的,意味着如上的代码会解释为:
(std::cin>>foo)>>bar;
换句话说,如果我们将operator>>变为一个普通的函数名称,如readFrom(),将变为这样的表达式:
readFrom(readFrom(std::cin,foo),bar);
我们总是从最内部开始计算表达式。因为 operator>>的左结合性,就成了最左边表达式std::cin>>foo。该表达式返回std::cin (更合适的,他返回一个它左边参数的引用)给下一个表达式。下一个表达式也返回(一个引用)给std::cin,但第二个引用被忽略了,因为它是这个“表达式语句”的最外边的表达式了。
另外:http://www.sunistudio.com/cppfaq/input-output.html 有几个关于类似问题的FAQ,楼主可以去看看Top
4 楼wanfustudio(雁南飞:知识之败,慕虚名而不务潜修也)回复于 2006-06-01 13:10:24 得分 0
汗~
有返回值呗
Top
5 楼sharpdew(风刃)回复于 2006-06-01 13:13:41 得分 5
编译器调用一个称为std::istream::operatorvoid*()的成员函数来将std::istream转换成布尔。它返回一个被转换成布尔的void*指针(NULL成为false,任何其他的指针成为true)。因此在这里,编译器产生了std::cin.operatorvoid*()的调用,就如同你象(void*)std::cin这样显式地强制类型转换。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
我同意这段话,因为我查看了istream的源码,发现其父类中的确有这样一个成员函数:
operator void*() const { return fail() ? (void*)0 : (void*)(-1); }Top
6 楼sharpdew(风刃)回复于 2006-06-01 13:16:21 得分 0
而且我单步调试的确是调用了这个转化函数,所以http://www.sunistudio.com/cppfaq/上说的没问题,确如所言。Top
7 楼Gucciwu(一意孤行 www.57studio.net)回复于 2006-06-01 13:21:37 得分 0
谢谢LoveVV99(LoveVV)和sharpdew(风刃)的解答,我大概明白了.Top




