这个输出的原因是什么?

时间:2013-08-25 07:24:02

标签: c++

我有以下代码。

    int x=80;
    int &y=x;
    x++;
    cout<<x<<" "<<--y;

输出结果是80 80.我不明白怎么做。我认为x的输出是81,尽管我对y一无所知。参数变量如何受减量运算符的影响。有人可以解释一下吗?

4 个答案:

答案 0 :(得分:19)

表达式评估为:

((cout << x) << " ") << --y;

在表达式的左侧和右侧的评估之间没有序列点(或排序),编译器可以输出评估--y的代码作为第一步。

由于y是对x的引用,因此这实际上是未定义的行为,因为您在同一表达式中读取和写入x而没有插入序列点。< / p>

答案 1 :(得分:6)

关于重定向运算符<<的一个令人讨厌的事情是它们直观地传达了一个确实不存在的“顺序计算”的缺陷。

写作时

std::cout << f() << g() << std::endl;

输出将首先显示f()的结果,然后显示g()的结果,但实际调用g()可能会在调用之前发生f()

它甚至比这更糟糕......并不是序列不可预测,但确实序列的概念无效。在

std::cout << f(g()) << h(i()) << std::endl;

例如合法的是,被调用的第一个函数是g(),后跟i(),后跟h(),最后是f()。甚至不能保证所有调用的顺序都是相同的(不是因为编译器制造商喜欢取笑你,而是因为代码可以内联,如果包含的函数在不同的上下文中内联,编译器可能会决定不同的顺序)。

保证评估顺序中序列的唯一C ++运算符是:

  1. &&:首先评估左侧,仅当结果为“true”时评估右侧
  2. ||:首先评估左侧,仅当结果为“false”时评估右侧
  3. ?::首先评估条件,然后仅评估第二个或第三个操作数
  4. ,:逗号运算符...计算左侧,删除值,然后计算并返回右侧。注意:函数参数之间的逗号不是逗号运算符,也不会强制执行评估顺序。
  5. 此外,此guaratee仅对预定义的运算符有效。如果您在班级中重载&&||,,则他们只是普通的运营商,对评估顺序没有任何特殊限制。

    任何其他运营商都不会对评估订单施加任何限制,这包括<<,即使使用类型会让您想到这一点。

答案 2 :(得分:1)

这是未定义的行为,C / C ++标准没有定义参数被推入堆栈的方式,并且通常以相反的顺序推送参数,例如:

func(1, 2)

将被评估为:

push 2
push 1
call func

因此,在您的情况下,--y会在x之前进行评估和推送。在这个例子中很清楚:

#include <iostream>

int a() { std::cout << "a" << std::endl ; return 1; }
int b() { std::cout << "b" << std::endl ; return 2; }

int main(void) {

    std::cout << a() << " " << b() << std::endl;

    return 0;
}

从第一眼看,它应该打印出来:

a
b
1 2

但它打印出来:

b
a
1 2

答案 3 :(得分:0)

x++

增加 x 并生成x的原始值作为表达式结果。

特别是,对于x ++, 没有为x的原始值的增量和生成隐含的时间顺序。 编译器可以自由地发出生成x的原始值,例如它可能存在于某个寄存器中,并将增量延迟到表达式结束(下一个序列点)。虽然x++似乎将 x 增加到 81 ,但直到打印才会执行此操作。根据{{​​1}},它会获得递增的值(81)并在打印之前递减它,因为它是前缀运算符。