还有链接插入操作符的其他问题吗?

时间:2014-04-04 00:14:28

标签: c++

所以,我今天早些时候正在搞乱C ++,尤其是链式插入运算符。我注意到一些对我来说很奇怪的东西。

#include <iostream>
using namespace std;

size_t& foo(size_t& n) {
    ++n;
    return n;
}

int main() {
    size_t bar = 5;
    cout << bar << " a " << foo(bar) << " b " << bar;
    cin >> bar;    //Ignore this, it's only here as an easy way to keep the window open
}

运行此功能,而非实际提供5 a 6 b 6 6 a 6 b 5。显然,插入操作数从右到左进行计算,然后从左到右进行打印,这可以解释为什么更新后的值出现在函数调用之前,以及之后的原始值。

当然,这可以通过简单地将cout foo(bar)放在自己的行上来解决,但我离题了。

在链接插入运算符时,我是否应该注意其他任何奇怪的事情?另外,有没有人知道为什么插入操作符会这样做?

2 个答案:

答案 0 :(得分:5)

您正在读取两次条形码并为函数调用引用它一次,这会使其递增。对于读取而言,该函数调用是不确定地排序的,这些读取对彼此是不相关的,因此允许任何排序,并且未指定它。

你没有完全未定义的行为(一切顺利),但未指定的行为并不是更有趣。这是四个有效的输出:

5 a 6 b 5
5 a 6 b 6
6 a 6 b 5
6 a 6 b 6

答案 1 :(得分:3)

&#34;链接插入操作符&#34;只是函数调用。 C ++对该语句中的函数调用有一些简单的规则:

  1. 单个语句中的函数调用不会交错 - 一个在下一个语句开始之前完成。 (即声明中没有多线程)
  2. 当一个函数调用的返回值是另一个函数调用的参数时,第一个函数调用必须在第二个函数调用之前发生。
  3. 没有规则必须连续或在调用之前立即评估单个函数的多个参数 - 排序规则集非常短。

    现在我们在链中看到的是,不同的operator<<调用确实是链接的:第二个调用使用第一个调用的返回值。这就是为什么这些运营商都返回std::ostream&的原因。因此,您的输出将以正确的顺序显示。

    在打印其返回值之前,必须使用相同逻辑的

    foo(bar)调用。但它可以在任何时间调用。回想一下,没有规则必须同时评估单个函数的2个参数。第三个operator<<调用的两个参数是foo(bar)的返回值和第二个operator<<的返回值。因此,当打印第三个值时,两者都必须发生。因此,a之后打印的数字是6。

    如果你声明结果应该是5 a 6 b 6,那么你假设在第三次调用的第二个参数之后计算第五个调用的第二个参数。根本就没有规则。