在大一的时候就遇到的一个当时一直懂得不太透彻的问题: 使用函数来交换两个变量的值. 现在常常用到algorithm
头文件里的swap
函数, 因此决定整理一下这个问题. 希望能对后来者有所帮助.
首先, 要知道的一个结论是函数参数的传递是单向的, 也就是实参→形参, 无法完成形参→实参的参数传递.
因此, 像下面这种写法无法完成两个变量值的交换:
void swap(int a, int b) {
int temp;
temp = a;
a = b;
b = temp;
}
可以理解为这个函数中的a和b都是由实参赋值过来, 但是在不知道实参地址的情况下是没有办法向实参赋值的, 而且这个函数内部的两个变量的作用域只有这个函数, 函数执行完毕后a和b都被释放.
同样地,下面这种做法也没有办法实现变量值的交换:
void swap(int * a, int *b){
int * temp=a;
a=b;
b=temp;
}
这种写法的思想在于直接把两个地址进行交换, 错误地认为地址交换后值也就交换了, 其实,这种想法的误区和上面的误区相同: 错误地认为,swap
函数里面交换完地址后main
函数里面的地址也交换了, (上面的误区是认为swap
函数里的变量交换完成后main
函数里的变量也交换了), 地址也只是一个"无符号的整型"数据,其本身也跟普通变量一样是值的传递, 区别在于,我们可以通过这个值来去物理内存中找到的具体地址空间, 然后对这个地址空间进行访问.
下面这种做法就是通过这个地址来对物理内存进行访问从而进行变量值的交换.
void swap(int *a, int *b) {
int temp;
temp = *a;
*a = *b;
*b = temp;
}
这里要注意的是,有些时候我们可能会把这个函数写成如下形式:
void swap(int *a, int *b) {
int *temp;
*temp = *a;
*a = *b;
*b = *temp;
}
这里是许多初学者都会犯的错误, 这个函数的问题在于: temp
指针没有被初始化(也就是"野指针"),他可能会指向某些系统工作内存, 这样的话就会出错.
因此,我们可以把上面这个函数进行如下修改即可以实现两个变量值的交换:
void swap(int *a, int *b) {
int x;
int *temp= &x;
*temp = *a;
*a = *b;
*b = *temp;
}
最后还有一种方法来实现值的交换:引用.
void swap(int &a, int &b) {
int temp;
temp = a;
a = b;
b = temp;
}
这里swap
的参数变成了两者引用, 引用可以理解为传进来的实参的另一个别名, 他们所指向的地址空间为同一个地址空间, 因此当对引用的值进行改变的时候, 实参的值也会改变.
此外,还有一些方法如采用全局变量, 静态变量等等方法来实现值的交换,这里不做赘述.
参考资料:
算法笔记 P66