以下代码:
myQueue.enqueue('a');
myQueue.enqueue('b');
cout << myQueue.dequeue() << myQueue.dequeue();
将“ba”打印到控制台
,同时:
myQueue.enqueue('a');
myQueue.enqueue('b');
cout << myQueue.dequeue();
cout << myQueue.dequeue();
打印“ab”为什么会这样?
似乎cout首先调用最外层(最接近;)函数并且正在运行,它的行为方式是什么?
答案 0 :(得分:29)
<<
运算符没有序列点,因此编译器可以首先自由评估dequeue
函数。保证的是第二个dequeue
调用的结果(按照它在表达式中出现的顺序而不一定是它的评估顺序)是<<
'的结果<<
'第一个(如果你得到我说的话)。
因此,编译器可以自由地将您的代码转换为某些内容(伪中间c ++)。这不是一个详尽的清单。
auto tmp2 = myQueue.dequeue();
auto tmp1 = myQueue.dequeue();
std::ostream& tmp3 = cout << tmp1;
tmp3 << tmp2;
或
auto tmp1 = myQueue.dequeue();
auto tmp2 = myQueue.dequeue();
std::ostream& tmp3 = cout << tmp1;
tmp3 << tmp2;
或
auto tmp1 = myQueue.dequeue();
std::ostream& tmp3 = cout << tmp1;
auto tmp2 = myQueue.dequeue();
tmp3 << tmp2;
这是临时表格在原始表达中所对应的内容。
cout << myQueue.dequeue() << myQueue.dequeue();
| | | | |
| |____ tmp1 _____| |_____ tmp2 ____|
| |
|________ tmp3 _________|
答案 1 :(得分:8)
来自你的例子的电话:
cout << myQueue.dequeue() << myQueue.dequeue();
通过两次operator<<
函数调用转换为以下表达式:
operator<<( operator<<( cout, myQueue.dequeue() ), myQueue.dequeue() );
-------------------- 1
---------2
cout
,myQueue.dequeue()
的评估顺序未指定。但是,operator<<
函数调用的顺序已明确指定,标记为1
和2
答案 2 :(得分:2)
自C ++ 17起,此代码的行为已更改; <<
的左操作数在<<
的右操作数之前排序,即使它是重载运算符也是如此。现在,输出必须为ab
。
有关更多信息,请参见:What are the evaluation order guarantees introduced by C++17?。