2011-04-19 102 views
1

C++的std :: cout似乎是一件有趣的事情。今天我尝试了我的C++编译器,下面的程序:奇怪的混合输出std :: cout

cout<<"!"<<"@"<<endl; 
cout<<"!"<<cout<<"@"<<endl; 
cout<<"!"<<(cout<<"@")<<endl; 

,输出相当好奇:

[email protected] 
[email protected] 
@!0x601068 

第一行是行人;第二个是可以理解的;然而,第三条线是我所不了解的。有人可以解释输出吗?谢谢各位提前!

Ziyao Wei

回答

5

这条线:

cout<<"!"<<(cout<<"@")<<endl; 

这是第一次执行:

(cout << "@") 

注:它可能执行别的第一,但是编译器优化这个子表达式,并发现它可以移动这个直到声明的开头,没有违反任何限制。

该表达式的结果是流(cout)。因此产生的表达式:

cout<<"!"<< cout <<endl; 

这导致:

@!<pointer> 
+0

你确定它是一个优化,导致子表达要先发生?我认为这是做到这一点的顺序点。 – quamrana 2011-04-19 21:56:33

+0

在语句的开始和结尾处有一个序列点。每次调用方法前后的序列点(注:operator <<是方法调用)。其他一切都可以移动。这里唯一的限制是''(cout <<“@”)'在用作参数之前必须完全评估。天气是在第一次方法调用之前或之后完成的,取决于编译器正在做什么优化。 – 2011-04-19 23:32:19

1

这第三行说明了插入算子的语法糖。

本质上,(cout<<"@")表达式首先被计算,结果产生@,返回流cout本身。

它只有那么第一个!,其次是表达式发送到cout

及其等效于:

operator<<(operator<<(operator<<(cout,"!"), (operator<<(cout,"@"))), endl); 
               ^------------------^ 

突出显示的部分是具有被称为任何功能之前被求值的表达式。

0

我的猜想 - 第3行的圆括号首先执行cout<<"@",这将@置于行首。然后执行cout.operator<<("!"),将!置于适当位置。然后ostreamcout.operator<<("!")返回运行它的operator<<(),给出ostream返回cout<<"@",从而输出0x601068

0

如果你明白的第二行,为什么第三迷惑你?

首先,评估括号中的表达式(但评估顺序未指定),因此@写在标准输出上;这种表达式返回对cout的引用,正如插入操作符一样,否则它们将无法链接。

现在这部分表达式被评估了,一切都按正常进行:线上的内容是从左到右写的:首先是!,然后是从括号中表达式返回的值(即引用cout然后endl

2

的parenthes这里影响评价的顺序如在任何其他表达(< <是操作者),由于表达式具有side-effects,发生在相同的顺序的表达评估那些副作用。