在学习C语言函数那一章节的时候我们第一次认识了swap。当时书上举这个例子是为了说明函数的“单向值传递”原理,即在函数调用的时候,实参总是将自己的值单向传递给形参,而不能反过来,并且在这个过程中形参的改变不会导致实参的改变。后来,我们又学习了指针,然后知道在函数调用的时候,实参还可以是一个变量的地址或者指针,即所谓的传址,并且知道传址调用过程中形参的改变会导致实参变化。再后来,我们还学习了C++程序设计语言,了解到在C++中还有一种函数参数的传递方式即“引用调用”,而且引用调用过程中形参的变化也会引起实参的变化!
上面说了那么多,无非说了两件事,第一,函数参数的传递方式有三种方式,即传值、传址和引用调用;第二,传值调用中形参的改变不会导致实参的变化,而传址和引用调用中形参的变化则会导致实参的变化。为了加深印象,下面给出几个关于swap函数的例子:
先看两个传值调用的程序:
--------------------------------------------------------------------------------------------
//example_1
#include<iostream>
using namespace std;
void swap(int a,int b)
{
int t;
cout<<"In swap,Begin:"<<"a="<<a<<",b="<<b<<endl;
t=a;
a=b;
b=t;
cout<<"In swap,End:"<<"a="<<a<<",b="<<b<<endl;
}
int main()
{
int x=3,y=9;
cout<<"Befor swap:x="<<x<<",y="<<y<<endl;
swap(x,y);
cout<<"After swap:x="<<x<<",y="<<y<<endl;
return 0;
}
--------------------------------------------------------------------------------------------
结果为:
Befor swap:x=3,y=9
In swap,Begin:a=3,b=9
In swap,End:a=9,b=3
After swap,x=3,y=9
显然在函数调用过程中,形参发生了改变,但是实参没有发生变化,这是最典型的传值调用方式。
--------------------------------------------------------------------------------------------
//example_2
#include<iostream>
using namespace std;
void swap(int *a,int *b)
{
int *t;
cout<<"In swap,Begin:"<<"a="<<a<<",b="<<b<<endl;
t=a;
a=b;
b=t;
cout<<"In swap,End:"<<"a="<<a<<",b="<<b<<endl;
}
int main()
{
int x=3,y=9;
cout<<"Befor swap:x="<<x<<",y="<<y<<endl;
swap(&x,&y);
cout<<"After swap:x="<<x<<",y="<<y<<endl;
return 0;
}
--------------------------------------------------------------------------------------------
结果为:
Befor swap:x=3,y=9
In swap,Begin:a=0012FF7C,b=0012FF78
In swap,End:a=0012FF78,b=0012FF7C
After swap:x=3,y=9
在函数调用过程形参发生了交换,但是实参没有发生交换,这种方式表面上是传址(实参为地址),但是由于函数调用过程中实际上没有针对实参作出任何操作,其本质还是传值调用,故也将其划为传值调用。
接下来分别看两个传址和引用调用的粒子:
//example_3
#include<iostream>
using namespace std;
void swap(int *a,int *b)
{
int t;
cout<<"In swap,Begin:"<<"a="<<a<<",b="<<b<<endl;
t=*a;
*a=*b;
*b=t;
cout<<"In swap,End:"<<"a="<<a<<",b="<<b<<endl;
}
int main()
{
int x=3,y=9;
cout<<"Befor swap:x="<<x<<",y="<<y<<endl;
swap(&x,&y);
cout<<"After swap:x="<<x<<",y="<<y<<endl;
return 0;
}
--------------------------------------------------------------------------------------------
结果为:
Befor swap:x=3,y=9
In swap,Begin:a=0012FF7C,b=0012FF78
In swap,End:a=0012FF78,b=0012FF7C
After swap:x=3,y=9
可见在函数调用前后,形参没有发生变化,但是实参发生了变化,进行了交换。这是因为对形参的操作实际上就是对实参的操作。
--------------------------------------------------------------------------------------------
//example_4
#include<iostream>
using namespace std;
void swap(int &a,int &b)
{
int t;
cout<<"In swap,Begin:"<<"a="<<a<<",b="<<b<<endl;
t=a;
a=b;
b=t;
cout<<"In swap,End:"<<"a="<<a<<",b="<<b<<endl;
}
int main()
{
int x=3,y=9;
cout<<"Befor swap:x="<<x<<",y="<<y<<endl;
swap(x,y);
cout<<"After swap:x="<<x<<",y="<<y<<endl;
return 0;
}
结果为:
Befor swap:x=3,y=9
In swap,Begin:a=3,b=9
In swap,End:a=9,b=3
After swap:x=9,y=3
函数调用过程中形参和实参都发生了变化,这是因为形参是实参的别名的缘故。
最后再看一个可能很容易被判断为正确的例子:
void swap(int *a,int *b)
{
int *t;
*t=*a;
*a=*b;
*b=*t;
}
程序的main函数和上面各例子中的相同,这个程序编译和链接都是没有错误的,然而在运行时出错了!原因就在于swap函数中定义了一个指向整型变量的指针t,t没有初始化接下来就是用了*t来访问t所指向的存储单元的内容,这是很危险的!因为p很有可能指向的内存是非法的。
转载请注明出处:http://blog.csdn.net/collier/archive/2010/09/04/5862752.aspx