一道考察函数参数传递、值传递、指针传递(地址传递)、引用传递

时间:2022-04-18 21:30:59
#include<iostream>


using namespace std;


void swap1(int p, int q)
{
int temp;
temp =p;
p =q;
q = temp;
}
void swap2(int*p,int*q)
{
int * temp;
*temp = *p;
*p =*q;
*q =*temp;
}
void swap3(int*p, int*q)
{
int *temp;
temp =p;
p=q;
q=temp;
}
void swap4(int*p,int*q)
{
int temp;
temp =*p;
*p=*q;
*q =temp;
}
void swap5(int &p, int &q)
{
int temp;
temp=p;
p=q;
q=temp;


}
int main()
{
int a =2,b=4;
swap1(a,b);
//swap2(&a,&b);
  //swap3(&a,&b);
//swap4(&a,&b);
//swap5(a,b);


cout<<a<<" "<<b<<endl;

}

解析:swap1传的是值的副本,在函数体内被修改了形参p、q(实际参数a,b的一个拷贝),p、q的值确实交换了,但是它们是局部变量,不会影响到主函数中a,b。当swap1生命周期结束时,p、q所在栈也就被删除了。如下图所示:

一道考察函数参数传递、值传递、指针传递(地址传递)、引用传递

一道考察函数参数传递、值传递、指针传递(地址传递)、引用传递

    swap2传的是一个地址进去了,在函数体内的形参*p,*q是指向实际参数a、b的两个指针

这里注意:

int *temp;

*temp =*p;

      一道考察函数参数传递、值传递、指针传递(地址传递)、引用传递


是不符合逻辑的一段代码,int*temp 新建了一个指针(但没有分配内存)。*temp =*p不是指向而是拷贝。把*p所指向内存里的值(也就是实参a的值)拷贝到*temp的内存中去。但是int *temp不是不分配内存吗?的确不分配,于是系统在拷贝时临时给了一个随机地址,让它存值。分配的随机地址是个“意外”,且函数结束不收回,造成内存泄露。

一道考察函数参数传递、值传递、指针传递(地址传递)、引用传递

那么swap2到底能否实现两数交换吗?这要视编译器而定,笔者在Dev-C++可以通过测
试,但是在更加“严格”的编译器如vs2008,这段代码会报错。

swap3传递的一个地址进去,在函数体内的形参*p,*q是指向实际参数a,b地址的两个指针。这里要注意:

int* temp;

temp =p;

int *temp新建了一个指针(但没有分配内存)。temp =p 是指向而不是拷贝,temp指向了*p所指向的地址(也就是a)

而代码:

p =q;

q =temp;

意思是p指向了*q所指向的地址(也就是b)。q指向了*t所指向的地址(也就是a)如下图所示:

一道考察函数参数传递、值传递、指针传递(地址传递)、引用传递

一道考察函数参数传递、值传递、指针传递(地址传递)、引用传递

但是函数swap3不能实现两个数的交换,这是因为函数体内只是指针的变化,而对地址中的值没有改变。

举个简单的例子,a、 b两个仓库的两把备用钥匙p、 q,p钥匙用来开a仓
库,q钥匙用来开b仓库。 现在进入函数体,p、 q钥匙功能发生了改变:p钥匙用来开b仓
库,q钥匙用来开a仓库;但是仓库本身的货物没有变化(a仓库原来是韭菜现在还是韭菜,b
仓库原来是番薯现在还是番薯)。 当函数结束,p、 q两把备用钥匙自动销毁。 主函数里用主
钥匙打开a、 b两个仓库,发现值还是没有变化。


函数swap4 可以实现两个数的交换,因为它修改的是指针所指向地址中的值。如下图所示:

一道考察函数参数传递、值传递、指针传递(地址传递)、引用传递

一道考察函数参数传递、值传递、指针传递(地址传递)、引用传递

swap5函数和swap5类似,是一个引用传递,修改的结果直接影响实参。