指针或者引用作为形参

作者:573xmcgcg
链接:https://www.zhihu.com/question/30000523/answer/46387415
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

使用指针或者引用作为形参是为了解决按值传递可能导致的问题。所以这里再次讲一下使用指针,引用和值作为形参所导致的结果。C++教科书都会用一个交换两个变量的值的函数来举例:void swap(int a, int b); //使用指针和引用的情况下形参类型分别为int和int&
{
int temp;
//使用指针为形参的情况下需要将以下的a和b分别替换为
a和*b
temp = a;
a = b;
b = temp;
}
结果是怎么样的题主应该清楚:按值传递无法完成这一行为,而传递指针或者引用是可行的。那么原因是什么?在按值传递的情况下:int x = 4, y = 5;
swap(x, y);
//…main函数其它部分…
void swap(int a, int b)
{
int temp;
temp = a;
a = b;
b = temp;
}
第一步:编译器会在内存开辟两个能存放int型变量的区域(假设分别为0xAAAAAAAA和0xBBBBBBBB),用于保存x和y的值。第二步:swap函数接收x和y的值,编译器会另外开辟两个存放int型变量的区域(假设分别为0xCCCCCCCC和0xDDDDDDDD),将4和5分别赋给形参a和b。第三步:swap函数完成交换,此时形参a=5, b=4,但是实参x和y的值并没有发生变化。因为swap函数只交换了0xCCCCCCCC和0xDDDDDDDD两块区域储存的值,并没有影响到0xAAAAAAAA和0xBBBBBBBB。所以x和y本身没有受到swap函数的影响,交换失败。------------------------------------------------------------------------------------------------------------------------------------------形参为指针的情况下:int x = 4, y = 5;
int px = &x, py = &y;
swap(px, py);
//…main函数其它部分…
void swap(int
a, int
b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
第一步:编译器会在内存开辟两个能存放int型变量的区域(假设分别为0xAAAAAAAA和0xBBBBBBBB),用于保存x和y的值。第二步:编译器会在内存开辟两个能存放int型指针的区域(假设分别为0xCCCCCCCC和0xDDDDDDDD),两块区域分别存储x和y的地址(即0xAAAAAAAA和0xBBBBBBBB)第三步:swap函数接收px和py的值,编译器会另外开辟两个存放int型指针的区域(假设分别为0xEEEEEEEE和0xFFFFFFFF),将0xAAAAAAAA和0xBBBBBBBB分别赋给形参a和b。第四步:swap函数创造一个int型变量temp,假设地址为0xGGGGGGGG。------------------------------------------------------------------------------------------------------------------------------------------第五步:temp = *a;
*a的值就是x的值(即4),temp获得4这个值。------------------------------------------------------------------------------------------------------------------------------------------第六步:*a = *b;
形参a的值是0xAAAAAAAA,所以这一句将0xAAAAAAAA这一块内存所存储的值由4修改为5,而0xAAAAAAAA正是x的地址。也就是说x本身的值被改成了5。------------------------------------------------------------------------------------------------------------------------------------------第七步:*b = temp;
同理,形参b的值是0xBBBBBBBB,这一句将0xBBBBBBBB这一块内存所存储的值由5修改为4,而0xBBBBBBBB正是y的地址。也就是说y本身的值被改成了4。swap函数执行完毕后x和y的值分别为5和4,交换成功。在这种情况下,如果传入两个int型变量而不是int型指针,则编译不会通过。因为int型变量并不是地址,在a为int型变量的情况下,a并不是符号的合法用途。
------------------------------------------------------------------------------------------------------------------------------------------形参为引用的情况下:int x = 4, y = 5;
swap(x, y);
//…main函数其它部分…
void swap(int& a, int& b)
{
int temp;
temp = a;
a = b;
b = temp;
}
第一步:编译器会在内存开辟两个能存放int型变量的区域(假设分别为0xAAAAAAAA和0xBBBBBBBB),用于保存x和y的值。第二步:两个int型参数传入swap函数,函数将形参a和b分别声明为x和y的引用。此时a的地址和x一样是0xAAAAAAAA,b的地址和y一样是0xBBBBBBBB。第三步:此时swap函数交换a和b的值,由于a和b的地址分别与x和y的地址相同(即0xAAAAAAAA和0xBBBBBBBB),该函数完成了对x和y的值的交换。交换后0xAAAAAAAA存储的值为5,0xBBBBBBBB存储的值为4。当形参类型为引用时,实参和形参共享一个地址,对形参的修改也就是对实参的修改。可以看到,使用指针和引用分别实现交换变量值的机制是不同的。尽管两种方法都直接对x和y的地址储存的值进行了修改,但是当形参是指针时,a和b的值并未发生变化(依然分别是x和y的地址);而当形参是引用时,a和b的值发生了变化。------------------------------------------------------------------------------------------------------------------------------------------最后回到问题本身:为什么形参是引用int &,既可以是int &又可以是int呢?举个例子:#include
using namespace std;

int main()
{
int a = 1, b = 2; //声明并初始化两个int型变量
int *pa = &a, *pb = &b; //pa和pb分别为指向a和b的int型指针
int &ra = a, &rb = b; //ra和rb分别为指向a和b的int型引用

cout << "a*b=" << a*b <<endl;      //合法,输出为2
cout << "pa*pb=" << pa*pb << endl; //非法,编译报错
cout << "ra*rb=" << ra*rb << endl; //合法,输出同样为2

return 0;

}
在这个例子中,rarb的结果和ab完全一致,尽管ra和rb是指向int型变量的引用,但是ra和rb在被声明为引用以后也可以被当作int型变量进行处理。而pa和pb是指向int型变量的指针,它们存储的是a和b的地址而不是a和b的值,所以对pa和pb进行int型变量的运算是非法的。------------------------------------------------------------------------------------------------------------------------------------------如果说形参是引用int &,传int进去是为了绑定到实参上,那传一个已经绑定的int &进去是绑定什么呢?修改一下上面的例子:#include
using namespace std;

int main()
{
int a = 1, b = 2; //声明并初始化两个int型变量
int &ra = a, &rb = b; //ra和rb分别为指向a和b的int型引用
int &rra = ra, &rrb = rb; //rra和rrb分别为指向ra和rb的int型引用

cout << "a*b=" << a*b <<endl;          //合法,输出为2
cout << "ra*rb=" << ra*rb << endl;     //合法,输出同样为2
cout << "rra*rrb=" << rra*rrb << endl; //合法,输出依然为2

return 0;

}
在这个例子中,rra为指向【指向int型变量的引用】的引用,国内的C++教科书在讲到引用也会提一下指向引用的引用是合法的。在这种情况下,ra被引用是会被当作普通的int型变量处理。当一个int&参数传入swap函数的时候,同样地,该int&参数会被当作一个int型变量,然后形参就是这个变量的引用。所以在这种情况下传入int或int&的输出都是一样的。

已标记关键词 清除标记
相关推荐
<p> <b><span style="background-color:#FFE500;">【超实用课程内容】</span></b> </p> <p> <br /> </p> <p> <br /> </p> <p> 本课程内容包含讲解<span>解读Nginx的基础知识,</span><span>解读Nginx的核心知识、带领学员进行</span>高并发环境下的Nginx性能优化实战,让学生能够快速将所学融合到企业应用中。 </p> <p> <br /> </p> <p style="font-family:Helvetica;color:#3A4151;font-size:14px;background-color:#FFFFFF;"> <b><br /> </b> </p> <p style="font-family:Helvetica;color:#3A4151;font-size:14px;background-color:#FFFFFF;"> <b><span style="background-color:#FFE500;">【课程如何观看?】</span></b> </p> <p style="font-family:Helvetica;color:#3A4151;font-size:14px;background-color:#FFFFFF;"> PC端:<a href="https://edu.csdn.net/course/detail/26277"><span id="__kindeditor_bookmark_start_21__"></span></a><a href="https://edu.csdn.net/course/detail/27216">https://edu.csdn.net/course/detail/27216</a> </p> <p style="font-family:Helvetica;color:#3A4151;font-size:14px;background-color:#FFFFFF;"> 移动端:CSDN 学院APP(注意不是CSDN APP哦) </p> <p style="font-family:Helvetica;color:#3A4151;font-size:14px;background-color:#FFFFFF;"> 本课程为录播课,课程永久有效观看时长,大家可以抓紧时间学习后一起讨论哦~ </p> <p style="font-family:"color:#3A4151;font-size:14px;background-color:#FFFFFF;"> <br /> </p> <p class="ql-long-24357476" style="font-family:"color:#3A4151;font-size:14px;background-color:#FFFFFF;"> <strong><span style="background-color:#FFE500;">【学员专享增值服务】</span></strong> </p> <p class="ql-long-24357476" style="font-family:"color:#3A4151;font-size:14px;background-color:#FFFFFF;"> <b>源码开放</b> </p> <p class="ql-long-24357476" style="font-family:"color:#3A4151;font-size:14px;background-color:#FFFFFF;"> 课件、课程案例代码完全开放给你,你可以根据所学知识,自行修改、优化 </p> <p class="ql-long-24357476" style="font-family:"color:#3A4151;font-size:14px;background-color:#FFFFFF;"> 下载方式:电脑登录<a href="https://edu.csdn.net/course/detail/26277"></a><a href="https://edu.csdn.net/course/detail/27216">https://edu.csdn.net/course/detail/27216</a>,播放页面右侧点击课件进行资料打包下载 </p> <p> <br /> </p> <p> <br /> </p> <p> <br /> </p>
©️2020 CSDN 皮肤主题: 黑客帝国 设计师:白松林 返回首页