失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > c++中函数参数传递(值传递 指针传递 引用传递)进一步认识

c++中函数参数传递(值传递 指针传递 引用传递)进一步认识

时间:2019-12-08 19:14:28

相关推荐

c++中函数参数传递(值传递 指针传递 引用传递)进一步认识

【重点】:转自@richerg85,请有帮助的朋友一定去原作者处点赞,地址:/richerg85/article/details/14450183

从函数中把我需要的两个值传出来,由于传出来的值比较多,所以不考虑用return来返回,需要通过参数把修改后的值拉出来供我使用,很当然的就想到了用指针,但是值就是传不出来;使我对原有的大脑中指针的思维产生混沌感,今天一上午才把函数传递又走了一遍,才明白其中道理(道行还是很浅),现在整理如下:

我之前写的方法部分代码,相信好多人都是这么写的:[cpp]view plain copyBOOLGetStartEndBoxes(BOOLbRow,constSwCrsrShell&rShell,SwTableBox*pStt,SwTableBox*pEnd) { SwSelBoxesaBoxes; ...... pStt=aBoxes[0]; pEnd=aBoxes[aBoxes.Count()-1]; returnTRUE; } 调用: 。。。。。。SwTableBox*pStt=0; SwTableBox*pEnd=0; if(!GetStartEndBoxes(bRow,*this,pStt,pEnd)) returnFALSE;

传递一个指针到调用函数,希望获得更新后的值(pStt, pEnd),为什么没有获得到呢?

概念

首先从概念上来说一下这几种函数传参方式及区别: 1、值传递:形参是实参的拷贝,改变函数形参的值并不会影响外部实参的值,这是最常用的一种传参方法,也是最简单的一种传参方法,只需要传递参数,返回值那是return考虑的; 2、指针传递:指针传递参数从本质上来说也是值传递,它传递的是一个地址。【值传递过程中,被调函数的形参作为被调函数的局部变量来处理,即在函数内的栈中开辟内存空间以存放由主调函数放进来的实参的值,从而成了实参的一个副本(记住这个,函数内参数的是实参的副本)】。由于指针传递的是外部实参的地址,当被调函数的形参值发生改变时,自然外部实参值也发生改变。 3、引用传递:被调函数的形参虽然也作为局部变量在栈中开辟了内存空间,但是栈中存放的是由主调函数放进的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过栈中存放的地址访问主调函数中实参变量(实参和形参通过引用,合二为一,说白点就是:一个人,有两个名字那种;后面想会详细说)。因此,形参的任何改动都会直接影响到实参。

实例

先从简单的例子开始: 值传递:例子略过。指针传递:[cpp]view plain copyvoidswap(int*a,int*b) { inttemp; temp=*a; *a=*b; *b=temp; cout<<"a="<<a<<","<<"b="<<b<<endl; cout<<"*a="<<*a<<","<<"*b="<<*b<<endl; cout<<"&a="<<&a<<","<<"&b="<<&b<<endl; } (刚上大学的时候就接触过的例子,交换值) 调用:[cpp]view plain copyintmain(){ intx=1; inty=2; cout<<"x="<<x<<","<<"y="<<y<<endl; cout<<"&x="<<&x<<","<<"&y="<<&y<<endl; swap(&x,&y); } 一定要记住这种调用方式[cpp]view plain copyswap(&x,&y); 如指针传递的概念上所述,传地址给形参。 形如:int *a = &x;//用于指针传递,a有自己独立的内存地址,存储的内容是x的地址,*a是存x的值。 输出结果:

传入值的各变量的初始状态(地址状态): 从上图关系可以知道: a(b)是一个指向外部实参地址的指针,*a(*b)是指针的内容,如果改变了*a(*b)也必然导致外部实参的改变。

交换后:*a=2,*b=1;这样的结果是由于a或者b指针指向x或者y的地址的缘故,因此由于*a,*b值得交换导致外部实参发生变化。

思考一下,下面的操作能否实现值得变化? 简单测试代码:[cpp]view plain copyintchange(char*name){ cout<<"*******CHANGE--BEFORE******"<<endl; cout<<"name="<<name<<endl; cout<<"*name="<<&name<<endl; name="alter"; cout<<"*******CHANGE--AFTER********"<<endl; cout<<"name="<<name<<endl; cout<<"*name="<<&name<<endl; return1; } intmain() { char*str="thisisatest"; cout<<"******MAIN--BEFORE*****"<<endl; cout<<"str="<<str<<endl; cout<<"*str="<<&str<<endl; change(str); cout<<"*****MAIN--AFTER*****"<<endl; cout<<"str="<<str<<endl; cout<<"*str="<<&str<<endl; return1; } 执行结果: (打印的输出的时候,有点错误,*str应该为 &str)从结果中发现,并未达到改变值得效果,为什么?这个测试代码和本文开始的疑问是一样的,那就进一步分析: 传入值的各变量的初始状态(地址状态): 执行赋值操作[cpp]view plain copyname="alter";系统首先需要给字符串“alter”分配内存空间(地址),然后指针才指向其地址。所以*str并没有发生变化,因此最后打印出来的仍是“this is a test”,这也解释了我开始时的迷惑! 另一种成功传递参数的指针调用方法----指针的指针:[cpp]view plain copyvoidmy_malloc(void**p,intsize) { *p=malloc(sizeof(int)*size); } intmain() { int*a; my_malloc(&a,10); return1; } 执行结果: (有些参数没有用,只是为了打印出来看看) 当我们没有执行到给*p分配空间的时候: 执行malloc(size)后的图如下: 赋值给*p后:由于p指向&a即a的地址,*p则指向a的地址里的值,现在又要把分配的内存指向*p,所以,a的值即为新分配的内存!(这个比较难转圈) 然后,我们就给指针a分配内存成功了。3、引用传递:[cpp]view plain copyvoidswapref(int&a,int&b) { cout<<"******************beforeswapref:******************"<<endl; cout<<"a="<<a<<","<<"b="<<b<<endl; cout<<"&a="<<&a<<","<<"&b="<<&b<<endl; inttemp; temp=a; a=b; b=temp; cout<<"******************afterswapref:******************"<<endl; cout<<"a="<<a<<","<<"b="<<b<<endl; cout<<"&a="<<&a<<","<<"&b="<<&b<<endl; } intmain(){ intx=1; inty=2; cout<<"******MAIN--BEFORE*****"<<endl; cout<<"x="<<x<<","<<"y="<<y<<endl; cout<<"&x="<<&x<<","<<"&y="<<&y<<endl; //swap(&x,&y); swapref(x,y); cout<<"*****MAIN--AFTER*****"<<endl; cout<<"x="<<x<<","<<"y="<<y<<endl; cout<<"&x="<<&x<<","<<"&y="<<&y<<endl; } 一定要记住这种调用方式

[cpp]view plain copyswapref(x,y); 形如:int &a=x; //用于引用传递,可以理解为a就是x,x就是a,只不过名字不一样执行结果:这个具体就不分析了,记住引用传递实参和形参是一样的,只是名字不同而已。

如果觉得《c++中函数参数传递(值传递 指针传递 引用传递)进一步认识》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。