28

以下代码:

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 是首先调用最外层(最接近 ;)函数并进入其中,这是它的行为方式吗?

4

3 回答 3

31

运算符没有序列点,<<因此编译器可以先评估任dequeue一函数。可以保证的是,第二次dequeue调用的结果(按照它在表达式中出现的顺序,而不一定是计算它的顺序)被<<'ed 到第一个调用的结果<<(如果你得到我'我说)。

因此,编译器可以自由地将您的代码翻译成任何类似的东西(伪中间 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 _________|
于 2010-01-24T22:48:52.197 回答
8

您的示例中的调用:

cout << myQueue.dequeue() << myQueue.dequeue();

通过两次函数调用转换为以下表达式operator<<

operator<<( operator<<( cout, myQueue.dequeue() ), myQueue.dequeue() );
-------------------- 1
---------2

的评估顺序coutmyQueue.dequeue()指定。但是,operator<<函数调用的顺序是明确指定的,用1和标记2

于 2010-01-24T23:41:59.847 回答
5

自 C++17 以来,此代码的行为发生了变化;的左操作数<<在 的右操作数之前排序<<,即使它是重载运算符也是如此。输出现在必须是ab.

如需进一步阅读,请参阅:C++17 引入的评估顺序保证是什么?.

于 2018-06-27T04:31:51.320 回答