一、使用中间变量
void swap(int &a, int &b){//注意这里一定要是引用形参或指针,传值(int a)是错误的 int tmp=a; a=b; b=tmp; } void swap1(int *a,int *b){//a,b指向地址的内容作了交换 int tmp=*a; *a=*b; *b=tmp; }
为什么非引用形参void swap_0(int a,int b)是错误的??
编译器总是要为函数的非引用形参生成一个拷贝假设是_a, _b,如果函数体内的程序修改了_a,_b的内容,就导致参数a的内容作相应的修改。但a,b是局部变量,不会影响到主函数中原数p,q,当swap生命周期结束时,a,b也就消失了,不会传递给p,q。
二、不使用中间变量,最简单的方法是最安全的方法,下面的算法多少有问题:
(1)异或法。
异或法可以完成对整型变量的交换,对于浮点型变量它无法完成交换
如果交换的变量是自己,结果是0;(经过测试)
void swap3(int &a, int &b){ a=a^b; b=b^a; //b=a^b;也对 a=a^b; }
int a=1;
int &b=a;
swap3(a,b);//结果为0
(2)加减法。
void mySwap_1(float &a,float &b){ a=a+b; b=a-b; a=a-b; }
该方法可以交换整型和浮点型数值的变量,但在处理浮点型的时候有可能出现精度的损失,例如对数据:(以下经过测试)
a = 3.123456
b = 1234567.000000
交换后各变量值变为:
a = 1234567.000000
b = 3.125000
很明显,原来a的值在交换给b的过程中发生了精度损失。
(3)乘除法。
a = a * b;
b = a / b;
a = a / b;
乘除法更像是加减法向乘除运算的映射,它与加减法类似:可以处理整型和浮点型变量,但在处理浮点型变量时也存在精度损失问题。而且乘除法比加减法要多一条约束:b必不为0。
可能经验上的某种直觉告诉我们:加减法和乘除法可能会溢出,而且乘除的溢出会特别严重。其实不然,采用这两种方法都不会溢出。以加减法为例,第一步的加运算可能会造成溢出,但它所造成的溢出会在后边的减运算中被溢出回来。
***********错误的方法**********************************************************************************