前言
对于C++语言,在调用带参数的函数时,需要进行参数传递。参数传递提供了调用函数和被调用函数交换信息的渠道。参数传递的两种方法为传值、传引用。
函数定义的一般格式为:
< 返回值类型 > < 函数名 >(< 参数列表 >)
< 函数体 >
函数定义中的参数称为形式参数,简称形参。
函数调用的一般格式为:
< 函数名 > (< 参数列表 >)
括号内是提供给被调用函数的参数,称为实在参数,简称实参。
一、传值
1.简介
C++中的参数传递一般采用的是传值(call by value)方式,即传入的只是参数的值的复制,而不是参数的地址,因此被调用函数执行时,只能访问形式参数对应的内存单元(称为形式单元,单元中存放了实在参数的值),而【不能直接访问实在参数对应的单元】,因而【无法直接改变实在参数的值】。
2.代码实例
```cpp
#include <iostream>
using namespace std;
void swap(int x,int y) //传值
{
int temp;
temp=x;
x=y;
y=temp;
}
int main()
{
int x=10, y=20;
swap(x, y);
//把实在参数 x 和 y 的值传给了 swap 中形式参数 x 和 y
//(注意,实参 x、y 与形参x、y 是不同的变量,都有各自不同的存储单元)
cout <<″x:″ << x <<″y:″ << y << endl;
return 0;
}
程序输出是:
x:10 y:20。
证明交换失败。
swap 函数中交换的也只是形参 x 和 y这两个局部变量的值,修改的是形式单元中的值,当 swap 函数执行完后,控制返回main 函数的调用语句处,继续向下执行,此时形参 x 和 y 这两个局部变量也被撤销。
可见,在整个 swap 函数执行过程中,形式参数值的改变丝毫也没影响调用函数中实在参数x 和 y 的值。
3.问题分析
从上面的程序可以看出,参数传递允许信息从调用函数流向被调用函数,而被调用函数想要将数据传给调用函数,只能通过返回结果这一途径。在许多情况下,这一限制为程序设计带来了不便,因为它使得从被调用函数向调用函数传递的信息非常有限。
二、传引用
1.简介
为了弥补传值方法的不足,使被调用的函数能够访问调用它的函数的变量,C++还提供了传引用(callby reference)这一传递参数的方式。它是把对实参变量的引用传给形式参数,即将实参变量的地址存放到对应的形参的形式单元中。
传引用方法不仅可以将数据从调用函数传递给被调用函数,也可以通过形式参数访问调用函数中的实参变量,并进行各种操作,从而实现信息从被调用函数传向调用函数。
在说明形式参数时,参数名前要加上&符号,如果没有该符号,说明该参数按照传值方式进行传递。同一函数中,允许有的参数传引用,有的参数传值。
2.代码实例
#include <iostream>
using namespace std;
void swap(int &, int &); //(不必声明形参)
int main()
{
int x = 10, y = 20;
swap(x, y);
cout << "x:" << x << " y:" << y << endl;
return 0;
}
void swap(int & a,int & b)
{
int temp;
temp = a;
a = b;
b = temp;
}
程序输出是:
x:20 y:10。
证明交换成功。
3.问题分析
采取传引用方式,可将更多的数据从被调用函数传向调用函数。但它不是显式地修改调用程序中的变量,容易导致对变量的误修改。
三、补充
1.另一种选择(传指针的值)
#include <iostream>
using namespace std;
void swap(int *, int *); //(不必声明形参)
int main()
{
int x = 10, y = 20;
swap(&x, &y);
cout << "x:" << x << " y:" << y << endl;
return 0;
}
void swap(int * a,int * b)
{
int temp;
temp = *a; //此处的“ * ”符号代表取指针的值
*a = *b; //直接修改两个指针指向的地址的值
*b = temp;
}
程序输出是:
x:20 y:10。
证明交换成功。
2.相关知识汇总
首先要明确,“引用”类型变量的声明方式:【变量类型】 & 变量名。
“指针”类型的声明方式:【基类型 *】 变量名。
所以,“指针的引用类型”应当这样声明:【基类型 *】& 变量名。
基类型 * 是指针的声明方式。
void fun(int a) //传值,产生复制
void fun(int& a) //传引用,不产生复制
void fun(int* a) //传地址,产生复制,本质上是一种传值,这个值是地址
void fun(int* a) //传值,产生复制
void fun(int*& a) //传引用,不产生复制
void fun(int** a) //传地址,产生复制,本质上是一种传值,这个值是指针的地址
总结
注意两种方法的使用场合,尤其防止出现“该传引用结果传了值导致数值不能正确修改”的情况。