函数的传值与传址
副题:使用指针修改函数参数
题注:许多教程用的是“使用指针修改函数”,个人感觉实际上讲的传值和传址的特点,传值无法完成数据交换,传址可以实现数据交换。
副题:使用指针修改函数参数
题注:许多教程用的是“使用指针修改函数”,个人感觉实际上讲的传值和传址的特点,传值无法完成数据交换,传址可以实现数据交换。
函数传递参数时,只是把实参的复制品(拷贝)传给形参,而实参本身并不动。
所以要想让实参发生变化,应使用两种方式:
1、 return返回值。这种方式虽然不能改变实参的值,但是可以得到变化的值。
2、用指针传址。这种方式通过间接方式,修改实参所在地址的值,而改变实参。
传值:
例1,下面是想通过swap()函数调用来交换两个整数值的程序:
#include <iostream.h>
void swap(int x,int y)
{
int temp=x; //交换两个形参
x=y;
y=temp;
}
void main()
{
int a=3, b=8;
cout <<"a=" <<a <<", b=" <<b <<endl;
swap(a,b);
cout <<"after swapping.../n";
cout <<"a=" <<a <<", b=" <<b <<endl;
}
运行结果为:
a=3, b=8
after swapping...
a=3, b=8
由于函数参数值的传递是实参到形参的复制,被调函数内部对形参的修改并不反映到上层函数的实参中,致使 swap()中x和y作了交换,而main()中a和b并没有交换。
传址:
例如,下面的程序通过传递指针来实现整数值的交换:
void swap(int* x,int* y)
{
int temp = *x;
*x = *y;
*y = temp;
}
void main()
{
int a=3, b=8;
cout <<"a=" <<a <<", b=" <<b <<endl;
swap(&a,&b);
cout <<"after swapping.../n";
cout <<"a=" <<a <<", b=" <<b <<endl;
}
运行结果为:
a=3, b=8
after swapping...
a=8, b=3
形参与实参的结合为int *x = &a; 实现了指针的功能。在形参中对*x的操作,实际上是对实参中a的操作。
传递指针可以使函数“返回”更多的值。这里的“返回”不是函数返回类型描述返回值的返回,而是反映了上层函数中的变量给被调函数修改了。
由于指针可以间接访问变量,使得函数调用中值的返回变得灵活多样,可以更方便地实现函数之间的数据传递。
但是要看到,指针的灵活是以破坏函数的黑盒特性为代价的。它使函数可以访问本函数的栈空间以外的内存区域(函数的副作用初露端倪),以致引起了:
(1)可读性问题:因为间接访问比直接访问相对难理解, 传递地址比传递值的直观性要差,函数声明与定义也相对比较复杂。
(2)重用性问题:函数调用依赖于上层函数或整个外部内存空间的环境,丧失了黑盒的特性,所以无法作为公共的函数模块来使用。
(3)调试复杂性问题: 跟踪错误的区域从函数的局部栈空间扩大到整个内存空间。不但要跟踪变量,还要跟踪地址。错误现象从简单的不能得到相应的返回结果,扩展到系统环境遭破坏甚至死机
所以要想让实参发生变化,应使用两种方式:
1、 return返回值。这种方式虽然不能改变实参的值,但是可以得到变化的值。
2、用指针传址。这种方式通过间接方式,修改实参所在地址的值,而改变实参。
传值:
例1,下面是想通过swap()函数调用来交换两个整数值的程序:
#include <iostream.h>
void swap(int x,int y)
{
int temp=x; //交换两个形参
x=y;
y=temp;
}
void main()
{
int a=3, b=8;
cout <<"a=" <<a <<", b=" <<b <<endl;
swap(a,b);
cout <<"after swapping.../n";
cout <<"a=" <<a <<", b=" <<b <<endl;
}
运行结果为:
a=3, b=8
after swapping...
a=3, b=8
由于函数参数值的传递是实参到形参的复制,被调函数内部对形参的修改并不反映到上层函数的实参中,致使 swap()中x和y作了交换,而main()中a和b并没有交换。
传址:
例如,下面的程序通过传递指针来实现整数值的交换:
void swap(int* x,int* y)
{
int temp = *x;
*x = *y;
*y = temp;
}
void main()
{
int a=3, b=8;
cout <<"a=" <<a <<", b=" <<b <<endl;
swap(&a,&b);
cout <<"after swapping.../n";
cout <<"a=" <<a <<", b=" <<b <<endl;
}
运行结果为:
a=3, b=8
after swapping...
a=8, b=3
形参与实参的结合为int *x = &a; 实现了指针的功能。在形参中对*x的操作,实际上是对实参中a的操作。
传递指针可以使函数“返回”更多的值。这里的“返回”不是函数返回类型描述返回值的返回,而是反映了上层函数中的变量给被调函数修改了。
由于指针可以间接访问变量,使得函数调用中值的返回变得灵活多样,可以更方便地实现函数之间的数据传递。
但是要看到,指针的灵活是以破坏函数的黑盒特性为代价的。它使函数可以访问本函数的栈空间以外的内存区域(函数的副作用初露端倪),以致引起了:
(1)可读性问题:因为间接访问比直接访问相对难理解, 传递地址比传递值的直观性要差,函数声明与定义也相对比较复杂。
(2)重用性问题:函数调用依赖于上层函数或整个外部内存空间的环境,丧失了黑盒的特性,所以无法作为公共的函数模块来使用。
(3)调试复杂性问题: 跟踪错误的区域从函数的局部栈空间扩大到整个内存空间。不但要跟踪变量,还要跟踪地址。错误现象从简单的不能得到相应的返回结果,扩展到系统环境遭破坏甚至死机