下面的阐述的内容只是对前辈经验的整理。
由于早期计算机的内存容量很小,为了尽量节省空间,交换两变量值时不使用中间变量。但这可能暗藏着缺陷。
有一个巧妙的函数 swap 是这样编写的:
inline void swap(int &a, int &b) { a = a + b; //缺陷1: 可能产生上溢. b = a - b; a = a - b; }
引发缺陷 1 的原因是,当 a 和 b 的值比较大,相加之和的实际值大于 int 类型所能表示的数值范围,此时产生上溢。
当传入 swap 函数的实参来自同一变量时,将会引发另一个缺陷:
int a = 2; // 缺陷 2: 传入同一变量, 变量结果为 0. swap(a, a);
上面 swap 内联函数调用展开后如下:
a = a + a; a = a - a; a = a - a; // a 的值为 0.
以此,当传入 swap 函数的实参来自同一变量时,该变量的值变为 0,得到了错误的结果。
下面是一种改进方法:
inline void swap(const &a, const &b) { a = a ^ b; b = a ^ b; a = a ^ b; }
例如,a = 10110B,b = 01011B,交换过程如下:
(1) a = a ^ b:
a: 10110
b: 01011
a: 11101
(2) b = a ^ b:
a: 11101
b: 01011
b: 10110
(3) a = a ^ b:
a: 11101
b: 10110
a: 01011
也就是:
b = (a^b)^b = a^(b^b) = a^0 = a
a = (a^b)^a = (a^a)^b = 0^b = b