关于C++使用位运算交换变量值的分析
1、使用临时变量交换
交换变量的值,最常见的方法就是用临时变量。
void swap1(int& a, int& b){int c = a;a = b;b = c;
}
清晰明了。
2、位运算版
对于整数类型,相信很多人都见过下面方法,可以使用位运算,从而不借用临时变量
void swap2(int& a, int& b){a ^= b;b ^= a;a ^= b;
}
逻辑上相当于
void swap2(int& a, int& b){int c = a ^ b;int d = b ^ c; // == b ^ (a ^ b); int e = c ^ d; // == (a ^ b) ^ (b ^ (a ^ b));b = d;a = e;
}
根据异或性质,显然成立。
甚至能写成一行 a ^= b ^= a ^= b;
3、分析
可能有人觉得,CPU处理位运算很快,位运算版还没有使用额外变量,所以位运算版效率更高。
但是,这是错误的观念,swap2 比 swap1 效率低很多,这是因为虽然CPU处理位运算很快,但那是位运算和加减乘除比,要是和纯赋值比,你位运算还得往后稍稍,编译成汇编指令后,位运算版既要赋值,又要计算异或运算,指令数比版本1多的多。
我们来对比一下:
图中,明显能看到,位运算版实际效率很低。
其他问题
- 位运算版只能应用于整数(能进行比特异或的类型)
- 如果参数 a, b 为同一变量,则结果会出错。
swap2(a, a)
或导致 a 的值变成 0。
因此,位运算版交换 几乎没有优点可言,任何情况下,都不建议使用此方式进行变量交换。
4、通用版swap
template<typename T>
void swap(T& a, T& b){T c = std::move(a);a = std::move(b);b = std::move(c);
}
使用移动语义进行变量转移。