为什么单行XOR交换在Javascript中无法工作但在C++中可以?

4
在JavaScript中,如果我写:
var a = 6;
var b = 4;
a ^= b ^= a ^= b;
console.log(a, b);

结果将为0 6。
但如果我写:

var a = 6;
var b = 4;
a ^= b;
b ^= a; 
a ^= b;
console.log(a, b);

结果将是4 6。并且是正确的。

为什么这种单行的JavaScript XOR交换方式不起作用?
而在C++中为什么它能正常工作?


3
我不确定这是否在技术上也是有效的C ++。 - Veedrac
1
你确定单个语句 a ^= b ^= a ^= b; 等同于 三个 语句 a ^= b; b ^= a; a ^= b; 吗? - Some programmer dude
6
在C++中,这是未定义的行为。如果它似乎有效,那只是巧合。 - molbdnilo
2
在C++中,你可以写std::swap(a, b),它能够正常工作并且更短。 - Bo Persson
1个回答

6

在JavaScript中,表达式从左到右进行求值。

这意味着你的一行代码将按照以下方式进行求值:

   a ^= b ^= a ^= b;
=> a = a ^ (b = b ^ (a = a ^ b))
=> a = 6 ^ (b = 4 ^ (a = 6 ^ 4))
=> a = 6 ^ (b = 4 ^ 2)
=> a = 6 ^ 6 = 0
   b = 4 ^ 2 = 6

在C++中,如果你对同一对象进行无序修改,程序的结果是不确定的。

这告诉我们聪明的代码往往并不好用。


2
为什么C++中是无序的?这是因为运算符本身具有从右到左的结合性。 - rozina
@rozina 表达式 a ^= b ^= a ^= b 的值是未定义的行为,因为它没有包含序列点,但修改了 a 两次。https://dev59.com/Zm855IYBdhLWcg3wuG-W 有一个详细的答案和细节。 - Jens
@rozina 结合性关注的是运算符应用的顺序,而不影响运算符操作数的计算顺序。 - molbdnilo
运算符的结合性规则定义了相同优先级的相邻运算符的计算顺序。 c++ 运算符 - rcgldr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接