首页 > 技术文章 > 传递动态内存

yihujiu 2017-02-05 13:20 原文

下面5个函数哪个能够成功进行两个数的交换?[中国某互联网公司2009年12
月笔试题]

 

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

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

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

那么swap2到底能否实现两数交换吗?这要视编译器而定,笔者在Dev-C++可以通过测
试,但是在更加“严格”的编译器如vs2008,这段代码会报错。
swap3传的是一个地址进去,在函数体内的形参*p、*q是指向实际参数a、b地址的两个
指针。这里要注意:

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

意思是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函数与swap4类似,是一个引用传递,修改的结果直接影响实参。
答案:swap4函数和swap5函数。

推荐阅读