一个 Java 中“效率最高”的交换两个值的方法令我迷惑 :a^=b^(b^=a^b)
java:
public class Swap{
public static void main(String [] args){
int a = 1,b = 2;
a^=b^(b^=a^b);
System.out.println(a+" "+b);
}
}
输出 : 2 1
(b^=a^b) 给 b 赋值为 1 ,注意此时前面的 b 并没有因为后面的赋值语句影响 b 的值, b^(b^=a^b) 等价于 2^1 = 3 , a^=3 所以 a = 2 。
c/c++:
#include<iostream>
using namespace std;
int main()
{
int a = 1,b = 2;
a^=b^(b^=a^b);
cout<<a<<" "<<b;
return 0;
}
输出 : 1 1
因为括号里表达式给 b 赋值为 1影响到了前面b的值 , 1^1 =0,a^=0 得 a=1, 所以输出 a =1,b=1
考虑编译器不同造成的后果:
在 Java 里:
int val = 3;
int x = val*(val+=2);
System.out.println(val+" "+x);
输出: 5 15
int val = 3;
int x = (val+=2)*val;
System.out.println(val+" "+x);
输出: 5 25
可见在 Java 中,赋值语句在前将对后面的该值产生影响,而对前面的该值不会影响,这是因为JVM中基本类型变量储存在栈中(见JVM内存管理机制)。
在 c/c++ 里:
int val = 3;
int x = val*(val+=2);
cout<<val<<x;
输出: 5 25
int val = 3;
int x = (val+=2)*val;
cout<<val<<x;
输出: 5 25
无论 val 写在赋值语句的前面还是后面 val 的值都将随着赋的值发生变化 。
结论:最好不要使用这种连续赋值结构,由于编译器的不同工作原理,最后的结果可能是不同的。
注:《Java解惑》中有提到这个问题,值得注意。