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

概念

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

   实例    

先从简单的例子开始:
  1.  值传递:例子略过。  
  2. 指针传递:
[cpp]  view plain copy
 
  1. void swap(int *a,int *b)  
  2. {  
  3.     int temp;  
  4.     temp=*a;  
  5.     *a=*b;  
  6.     *b=temp;  
  7.     cout<<"a=" <<a<<" ,"<<"b="<<b<<endl;  
  8.     cout<<"*a=" <<*a<<" ,"<<"*b="<<*b<<endl;  
  9.     cout<<"&a=" <<&a<<" ,"<<"&b="<<&b<<endl;  
  10. }  
(刚上大学的时候就接触过的例子,交换值)调用:
[cpp]  view plain copy
 
  1. int main(){  
  2.     int x=1;  
  3.     int y=2;  
  4.     cout<<"x=" <<x<<" ,"<<"y="<<y<<endl;  
  5.     cout<<"&x=" <<&x<<" ,"<<"&y="<<&y<<endl;  
  6.     swap(&x,&y);  
  7. }  
必定要记住这种调用方式
[cpp]  view plain copy
 
  1. swap(&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 copy
 
  1. int change(char* name){  
  2.     cout<<"*******CHANGE--BEFORE******"<<endl;  
  3.     cout<<"name=" <<name<<endl;  
  4.     cout<<"*name=" <<&name<<endl;  
  5.     name="alter";  
  6.     cout<<"*******CHANGE--AFTER********"<<endl;  
  7.     cout<<"name=" <<name<<endl;  
  8.     cout<<"*name=" <<&name<<endl;  
  9.     return 1;  
  10. }  
  11. int main()  
  12. {  
  13.     char *str = "this is a test";  
  14.   
  15.     cout<<"******MAIN--BEFORE*****"<<endl;  
  16.     cout<<"str=" <<str<<endl;  
  17.     cout<<"*str=" <<&str<<endl;  
  18.     change(str);  
  19.     cout<<"*****MAIN--AFTER*****"<<endl;  
  20.     cout<<"str=" <<str<<endl;  
  21.     cout<<"*str=" <<&str<<endl;  
  22.     return 1;  
  23. }  
    执行结果: (打印的输出的时候,有点错误,*str应该为 &str)
    从结果中发现,并未达到改变值得效果,为何?这个测试代码和本文开始的疑问是同样的,那就进一步分析:
    
    传入值的各变量的初始状态(地址状态):
     
   执行赋值操做
[cpp]  view plain copy
 
  1. name="alter";  
    系统首先须要给字符串“alter”分配内存空间(地址),而后指针才指向其地址。
        
 
 因此*str并无发生变化,所以最后打印出来的还是“this is a test”,这也解释了我开始时的迷惑! 微笑
 
另外一种成功传递参数的指针调用方法----指针的指针:
  
[cpp]  view plain copy
 
  1. void my_malloc(void** p, int size)  
  2. {  
  3.     *p = malloc(sizeof(int)*size);  
  4. }  
  5. int main()  
  6. {  
  7.     int *a;  
  8.     my_malloc(&a , 10);  
  9.     return 1;  
  10. }  
执行结果: (有些参数没有用,只是为了打印出来看看)
当咱们没有执行到给*p分配空间的时候:
执行malloc(size) 后的图以下:
 
   赋值给*p后:因为p指向&a即a的地址,*p则指向a的地址里的值,如今又要把分配的内存指向*p,因此,a的值即为新分配的内存!(这个比较难转圈
   
    
    而后,咱们就给指针a 分配内存成功了。
     三、引用传递:
     
[cpp]  view plain copy
 
  1. void swapref(int &a,int &b)  
  2. {  
  3.     cout << "******************before swapref:******************"<<endl;  
  4.     cout<<"a=" <<a<<" ,"<<"b="<<b<<endl;  
  5.     cout<<"&a=" <<&a<<" ,"<<"&b="<<&b<<endl;  
  6.     int temp;  
  7.     temp=a;  
  8.     a=b;  
  9.     b=temp;  
  10.     cout << "******************after swapref:******************"<<endl;  
  11.     cout<<"a=" <<a<<" ,"<<"b="<<b<<endl;  
  12.     cout<<"&a=" <<&a<<" ,"<<"&b="<<&b<<endl;  
  13. }  
  14. int main(){  
  15.     int x=1;  
  16.     int y=2;  
  17.     cout<<"******MAIN--BEFORE*****"<<endl;  
  18.     cout<<"x=" <<x<<" ,"<<"y="<<y<<endl;  
  19.     cout<<"&x=" <<&x<<" ,"<<"&y="<<&y<<endl;  
  20.     //swap(&x,&y);  
  21.     swapref(x, y);  
  22.     cout<<"*****MAIN--AFTER*****"<<endl;  
  23.     cout<<"x=" <<x<<" ,"<<"y="<<y<<endl;  
  24.     cout<<"&x=" <<&x<<" ,"<<"&y="<<&y<<endl;  
  25. }  
必定要记住这种调用方式
[cpp]  view plain copy
 
  1. swapref(x, y);  
形如:int &a=x; // 用于引用传递,能够理解为a就是x,x就是a,只不过名字不同
执行结果:
    这个具体就不分析了,记住引用传递实参和形参是同样的,只是名字不一样而已。
 
 
总结:
       本文重点仍是在参数传指针方面,指针确实使人头疼,今天遇到了,会出错,弄明白之后,等过段时间,又忘了,又遇到错误,再来看,这样不断反复,但愿能不断的提高,对指针的认识不断的加深!
       写了一下午,边琢磨、边参考、边实验,但愿对你有用!错误之处敬请见谅!
 
相关文章
相关标签/搜索