2013-08-25 52 views
14

我有以下代码。这个输出的原因是什么?

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

输出结果是80 80.我不明白怎么回事。我认为x的输出是81,但我对y没有任何了解。参考变量如何受减量运算符影响。有人可以解释吗?

+1

也许这个问题应该有助于澄清你:什么是C++指针变量和引用变量之间的区别是什么? (http://stackoverflow.com/questions/57483/what-are-the-differences-between-pointer-variable-and-reference-variable-in-c) – yasouser

+0

这类似于(到http://stackoverflow.com /问题/ 18426473 /预增 - 不工作,AS-I-期望/ 18426505#18426505)。 你缺少一个序列点。 –

回答

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. &&:首先评估左侧且仅当结果为“真”的计算结果的右侧
  2. ||:首先评估只有在结果为“假”时评估右侧
  3. ?::首先评估条件,然后仅评估第二或第三个操作数
  4. ,:逗号运算符...评估左侧,丢弃该值,然后评估并返回右侧。注:函数参数之间的逗号不是逗号运算符,也不会执行评估命令。

而且这guaratee只针对预定义的运算符有效。如果您的班级中存在&&||,,他们只是普通的操作员,对评估顺序没有任何特殊限制。

任何其他运营商不征收评估顺序任何限制,这包括<<即便利用某种技巧,你以为。

19

计算表达式为:

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

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

由于yx这里的参考,这是因为你无论从阅读和中间没有顺序点在同一个表达式写入x实际上未定义的行为。

+0

请检查编辑的代码这肯定与指针算术有关。当我们说y有一个地址x即80,并尝试和减少y时,它也不会在我的系统上递减。 –

+4

@SanyamGoel:这是未定义的行为。不同的编译器可以(也将会)输出不同的东西。 LHS和RHS的评估顺序是实现定义的,加上对'x'的读取和写入,没有顺序点=>未定义的行为(即它不是合适的C++,它可以做任何事情)。 – Mat

+0

建议编辑:*“请参阅[本SO线程](http://stackoverflow.com/questions/4176328/undefined-behavior-and-sequence-points)的详细解释。“* – jrok

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 
0
x++ 

增量X并产生作为表达式的结果是x的原始值。

特别是,对于x ++,没有时间顺序暗示增加和产生x的原始值。编译器可以自由发出产生x的原始值的机器码,例如,它可能出现在某个寄存器中,并且延迟增量直到表达式结束(下一个序列点)。虽然x++似乎增加x到,它不会直到打印。根据--y,它将获得增加的值(81)并在打印之前将其减少,因为它是前缀运算符。