指针与参数传递

本文详细解析了C/C++中参数传递的方式,包括值传递和引用传递的区别,以及形参与实参的概念。探讨了如何通过指针和引用改变实参的值,并对比了不同传递方式对程序效率的影响。

C/C++中参数传递问题

问题与解答:
1,值传递时,为什么被调用的方法中的形参值的改变不会影响到相应的实参?
   答:因为按值传递时,系统首先为被调用的方法的形参分配内存空间,然后把实参中的值按位置一一对应“复制”给形参。形参中存储的值只是一份实参的拷贝,因此被调用方法中形参值的任何改变都不会影响到相应的形参。

2,值传递和引用传递有什么不同,什么是值参数,它以什么方式传递?
   答:值传递时,系统首先为被调用方法的形参分配内存空间,并将实参的值按位置一一对应地复制给形参,此后,被调用方法中形参值得任何改变都不会影响到相应的实参; 而引用传递时,系统不是将实参本身的值复制后传递给形参,而是将其引用值(即地址值)传递给形参,因此,形参所引用的该地址上的变量与传递的实参相同,方法体内相应形参值得任何改变都将影响到作为引用传递的实参。

3,什么是形参,什么是实参?
   答:

   形参:在定义函数中指定的参数就是形参,在未出现函数调用时,他们并不占内存中的存储单元,只有在发生函数调用时,函数中的形参才被分配内存单元。在调用结束后,形参所占的内存单元也被释放。
  
   实参:实参可以是常量、变量和表达式,但要求有确定的值。在调用时将实参的值赋给形参。在内存中,实参单元和形参单元是不同的单元。在调用函数时,给形参分配存储单元,并将实参对应的值传递给形参,调用结束后,形参单元被释放,实参单元仍保留原值。
  
   理解:
        实参就是送进去方法中的东西~~行参就是把送进来的东西在方法中进行拷贝加工,加工完后方法就返回一个东西--返回值。

        值传递的时候,实参是不变的~形参是随着计算而变化的~~ 
        指针/引用传递的时候~~行参怎么变~实参就怎么变....
        

参数的传递分为:1.值方式参数传递,2.引用方式参数传递。
1)按值传递(不能改变实参)

    实参是变量,表达式等数值。

    函数调用的时候,实参和形参存在于内存中2快不同的区域,实参先自己复制一份拷贝,再把拷贝传给形参。由于是传递的是拷贝,所以实参不会受形参的影响,实参值不会被改变。

2)按地址传递(可以改变实参)

    实参是指针/引用。

    函数调用的时候,指针传给你,形参和实参指针都一样,对形参的任何操作就等于对实参的操做。实参的值就可以被改变。

 

总之,参数传递,在C语言中是系统对实参的一个副本拷贝,所以如果是值的传递,形参的改变是不会影响实参的,如果要有影响,在C中有个特别的概念,那就是指针,通过指针

可以直接在形参里操控实参的地址。

 C++为什么要有“引用传递”这回事?一种说法是只有引用才能达到操作符重载的目的,这个以后再谈。但是,撇开这个不谈,形参是不是引用,直接影响了程序执行的效率。前面提到过,函数调用时要用实参的值去初始化形参,初始化的过程包含了定义一个变量、然后给它赋一个值两个过程,如果这个变量并不是内部变量,而是一个类对象,那么,定义一个类对象可能很复杂,而初始化这个对象一样会很复杂。而引用只是给对象取一个别名,不涉及定义与初始化,离开作用域时也不用释放。
  相比之下,用指针传递可以避免类对象的定义、初始化与释放。只需要付出指针变量的定义、初始化与释放的代价。但是,指针的杀伤力太大。即使是熟练的程序员,也不能保证绝不出现“野指针”,野针的代价几乎无一例外是程序崩溃。
  引用也不是吃素的,如果说指针传递是“帮你配了一把我家的钥匙”,那么引用传递就是直接把我家的财产都交给了你。有时,我们使用引用传递仅仅是为了效率,而不希望实参被修改,那就要记得把形参标记为const,如“UINT GetLength(const CString&)”。
  顺便说一句,指针传递也可以这样做。把形参定义为指向const对象的指针(而不是const指针),可以降低杀伤力,保护实参所对应的内存。如果是普通的值传递,那么有没有const对函数外部并不影响。但是,我个人认为,有时候加上const也是一件好事。如果程序的逻辑并不需要改变参数,而实际上误写了代码,加上const可以让编译器帮我们找出BUG。

比较下下面的代码,它们在参数传递上实际上也就上面所说得地址传递,还是值传递的问题:

  1. //错误的方法:   
  2.   
  3. #include <stdio.h>   
  4.   
  5. #include <stdlib.h>   
  6. void Get(int *p)  
  7.   
  8. { p=(int *)malloc(sizeof(int));  
  9. }  
  10. int main()  
  11. {  
  12.     int *q=NULL;  
  13.     Get(q);  
  14.     printf("*q=%d/n",*q);  
  15.     return 0;  
  16. }   
  17. //下边是该例中正确的调用方法:   
  18.   
  19. #include <stdio.h>   
  20.   
  21. #include <stdlib.h>   
  22. void Get(int **p)  
  23. {  
  24. *p=(int *)malloc(sizeof(int));  
  25. }  
  26. int main()  
  27. {  
  28. int *q=NULL;  
  29. Get(&q);  
  30. printf("*q=%d/n",*q);  
  31.   
  32. //还有一种方法:   
  33. #include <stdio.h>   
  34. #include <stdlib.h>   
  35.   
  36. void Get(int *(&p))  
  37. {  
  38.     p=(int *)malloc(sizeof(int));  
  39. }  
  40.   
  41. int main()  
  42. {  
  43.     int *q=NULL;  
  44.     Get(q);  
  45.     printf("*q=%d/n",*q);  
  46.     return 0;  
  47. }  
  48. return 0;  
  49. }  

 关于指针的值的传递,其实在C++语言里,系统初始会为指针分配4个BYTES的长度的(长度由编译器决定,不同的编译器,指针长度可能会不一样,我这里VC为例),结合形参与实参之间传递是一种拷贝的关系,所以这里引入指针的指针参数传递。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JXES智能生态系统

如文章对你有用,请作者喝个咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值