C++中按引用传递参数
实参通常是通过值传递给函数的,这意味着形参接收的只是发送给它们的值的副本,它们存储在函数的本地内存中。对形参值进行的任何更改都不会影响原始实参的值。
然而,有时候可能会希望一个函数能够改变正在调用中的函数(即调用它的函数)中的一个值,这可以通过引用传递的方式来完成。
我们知道,变量是可以保存数据的内存位置的名称。当使用变量时,实际上就是访问存储在分配给它的内存位置的数据。引用变量是变量的另一个别名,它没有自己的存储数据的内存位置,它访问的是另一个变量的内存位置。对引用变量作出的任何更改,实际上都是对它所引用的变量内存位置中存储数据的更改。
当使用引用变量作为形参时,它将变为实参列表中相应变量的别名,对形参进行的任何更改都将真正更改正在调用它的函数中的变量。当以这种方式将数据传递给形参时,该实参被称为按引用传递。
引用变量的定义方法和常规变量类似,但是其数据类型和名称之间有一个 &
符号。例如,以下函数定义使形参 refVar 成为引用变量:
void doubleNum(int& refVar){ refVar *= 2;}
注意,变量 refVar 被称为“对 int 的引用”。
该函数将 refVar 乘以 2,因为 refVar 是引用变量,所以该操作实际上将对作为实参传递给函数的变量执行。
来看一下根据半径计算圆面积的函数:
// Function definitions (implementations)
double Area(double radius)
{
return Pi * radius * radius;
}
其中,参数 InputRadius 包含的值是在 main( )中调用函数时复制给它的:
// Call function "Area"
cout << "Area is: " << Area(radius) << endl;
这意味着函数调用不会影响 main( )中的变量 radius,因为 Area( )使用的是 radius 包含的值的拷贝。有时候,您可能希望函数修改的变量在其外部(如调用函数)中也可用,为此,可将形参的类型声明为引用。下面的 Area( )函数计算面积,并以参数的方式按引用返回它:
// output parameter result by reference
void Area(double radius, double& result)
{
result = Pi * radius * radius;
}
注意到该 Area()
函数接受两个参数。别遗漏了第二个形参 result 旁边的 &,它告诉编译器,不要将第二个实参复制给函数,而将指向该实参的引用传递给函数。返回类型变成了 void,因为该函数不再通过返回值提供计算得到的面积,而按引用以输出参数的方式提供它。如下的示例程序演示了如何按引用返回值,该程序计算圆的面积:
#include <iostream>
using namespace std;
const double Pi = 3.1416;
// output parameter result by reference
void Area(double radius, double& result)
{
result = Pi * radius * radius;
}
int main()
{
cout << "Enter radius: ";
double radius = 0;
cin >> radius;
double areaFetched = 0;
Area(radius, areaFetched);
cout << "The area is: " << areaFetched << endl;
return 0;
}
输出:
Enter radius: 2
The area is: 12.5664
分析:
注意到第 18 行调用函数 Area()
时提供了两个参数,其中第二个参数将包含结果。由于 Area()
的第二个参数是按引用传递的,因此 Area()
中第 8 行使用的变量 result,与 main()
中第 17 行声明的 double areaFetched 指向同一个内存单元。因此,在 main()
中,可以使用 Area()
中第 8 行计算得到的结果—第 20 行将其显示到屏幕上。
注意:
使用 return 语句时,函数只能返回一个值。因此,如果函数需要执行影响众多值的操作,且需要在调用者中使用这些值,则按引用传递参数是让函数将修改结果提供给调用模块的方式之一。
该文章会更新,欢迎大家批评指正。
推荐一个零声学院的C++服务器开发课程,个人觉得老师讲得不错,
分享给大家:Linux,Nginx,ZeroMQ,MySQL,Redis,
fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,
TCP/IP,协程,DPDK等技术内容
点击立即学习:C/C++后台高级服务器课程