以一个最简单的例子来说明参数传递的问题。
#include<iostream>
using namespace std;
void swap(int a,int b)
{
int temp;
temp = a;
a = b;
b = temp;
}
int main()
{
int a = 3;
int b= 4;
swap(a, b);
cout<<"a="<<a<<",b="<<b<<endl;
system("pause");
return 0;
}
结果如下:
a和b的值并没有发生变化。
下面说明主要原理和原因(个人理解,还在不断学习,可能存在一定偏差):
关于交换两个参数的数值,定义的函数可以有以下四种形式(仅声明):
void swap(int a,int b);
void swap(int &a,int &b);
void swap(int *a,int *b);
void swap(int *&a,int *&b);
对于第一种函数声明,定义如下:
void swap(int a,int b)
{
int temp;
temp = a;
a = b;
b = temp;
}
在这种函数的定义下,当主函数通过swap(a,b)
调用函数时,系统生成了a,b的副本供swap函数调用,也就是说,
系统原本给变量a和b分配的内存位置分别是0x0010和0x0014,当调用函数swap的时候,首先要为两个变量分别copy一个副本出来,这两个副本存放在内存中另外两个位置,swap函数调用的就是这两个副本。虽然函数执行了交换功能,但是交换的对象却是系统生成的副本,也就是说,对于原本的变量a和b并没有发生任何的改变,也就是开始函数执行结果的原因。
对于第二种函数声明,即void swap(int &a,int &b)
,整个函数的定义和调用如下:
#include<iostream>
using namespace std;
void swap(int &a, int &b)
{
int temp;
temp = a;
a = b;
b = temp;
}
int main()
{
int a = 3;
int b = 4;
swap(a, b);
cout << "a=" << a << ",b=" << b << endl;
system("pause");
return 0;
}
执行结果如下:
可以看到,两个变量实现了交换。
那么,这一种函数声明与第一种存在着什么差异呢?
因为这里采用了引用,也就是说,给变量取了一个别名,是为一个已存在的对象取的另外一个名字。对于别名的操作,就是对该对象的操作,使用引用的时候,系统在调用的时候,就不再为变量copy副本,直接在对象上面进行操作,因此,交换的结果能够正确反映出来。
第三种声明方式,void swap(int *a,int *b)
,即使用了指针,完整的定义和调用如下:
#include<iostream>
using namespace std;
void swap(int *a, int *b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
int main()
{
int a = 3;
int b = 4;
swap(&a, &b);
cout << "a=" << a << ",b=" << b << endl;
system("pause");
return 0;
}
执行结果如下:
可以看出,实现了变量交换的功能。
这样函数实现的过程是:
首先,主函数调用swap函数时,参数是两个变量的地址,即实际上,swap函数的调用是这样的:swap(0x0010,0x0014)
,在调用的时候,系统为这两个参数开辟新的内存空间存放其拷贝后的值,即图中下面有两块内存中存放的是这两个地址值。因此,函数在执行时,temp被赋值为第一个参数所对应的(地址里存放的)值,即temp=*(0x0010)=3
,第一个参数所对应的地址里存放的数值就被赋值为第二个地址里存放的数值。以此实现了交换功能。
第四种声明方式,void swap(int *&a,int *&b)
,这种方式将指针和引用结合起来,我暂时还没有完全搞明白,大致的理解是,如同第二种传递的是对象本身的引用,这种方式传递的是对象指针的引用。具体代码如下,暂时不是特别理解。
#include<iostream>
using namespace std;
void swap(int*& a)
{
cout << a << endl;
a = new int[5];
a[0] = 1;
}
int main()
{
int* a=(int *)0x00000001;
cout << a << endl;
swap(a);
cout << a[0] << endl;
cout << a[1] << endl;
system("pause");
return 0;
}