我们刚学编程的时候遇到需要交换两个变量的值时通常都会定义一个中间变量,比如:
#include <iostream>
int main()
{
int a = 4, b = 5;
int c = a;
a = b;
b = c;
std::cout << "a = "<<a<<std::endl<<"b = "<<b;
system("PAUSE");
}
以上就是很典型的变量换值的写法,花费了额外的中间变量c的内存,当变量是一个复杂的巨大的对象时可能会花费很多内存。有一种典型的不依赖中间变量换值得方法,如下:
#include <iostream>
int main()
{
int a = 4, b = 5;
a = a^b;
b = a^b;
a = a^b;
std::cout << "a = "<<a<<std::endl<<"b = "<<b;
system("PAUSE");
}
以上就是利用异或的位运算实现的变量互换,你可能会觉得很精巧,或者对位的逻辑操作比较难以理解。其实这个方法并不是唯一的写法,你只需要理解它的思路:
1、把a和b的差异存入a中;
2、根据a和b的差异以及b还原出a的值存入b中;
3、根据a和b的差异以及a的值(已存入b中)还原出b的值存入a中。
这样像你是不是思路大开?只要有一种方法能表示a和b的差异就可以了,并不一定要用异或运算。比如减法:
#include <iostream>
int main()
{
int a = 4, b = 5;
a = a - b;
b = a + b;
a = b - a;
std::cout << "a = "<<a<<std::endl<<"b = "<<b;
system("PAUSE");
}
这样写是不是一下子很简单了!你还可以用加法、乘法、除法、平方开根号……。不过需要注意加法乘法等会不会出现数据溢出和反转,开根号会不会导致运算效率降低。最推荐的方法还是使用异或运算法吧!
但是不用中间变量的互换数值函数是有坑,如下代码:
void swap(int a, int b)
{
a ^= b;
b ^= a;
a ^= b;
}
这个函数有一个致命的问题和一个潜在的问题。致命的问题是入参是按值传参,实际上并没有操作外部的数据,导致互换失败 。应该改为按引用或者指针传参。
void swap(int& a, int& b)
{
a ^= b;
b ^= a;
a ^= b;
}
潜在的问题是没有做入参检查,当a和b实际上是同一个地址的数据时是会出问题的,比如:
int main()
{
int a = 1;
int* b = &a;
swap(a, *b);
std::cout<<"a = "<<a<<" "<<"*b = "<<*b<<std::endl;
}
a = 0 *b = 0
请按任意键继续. . .
所以一定要做入参检查,正确的交换函数如下:
void swap(int& a, int& b)
{
if (a == b)
return;
a ^= b;
b ^= a;
a ^= b;
}