概念

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

实例

先从简单的例子开始:
  1. 值传递:例子略过。
  2. 指针传递:
  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. }
(刚上大学的时候就接触过的例子,交换值)调用:
  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. }
一定要记住这种调用方式

  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值得交换导致外部实参发生变化。
 
 
        思考一下,下面的操作能否实现值得变化?
        简单测试代码:

  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. cout<<"******MAIN--BEFORE*****"<<endl;
  15. cout<<"str=" <<str<<endl;
  16. cout<<"*str=" <<&str<<endl;
  17. change(str);
  18. cout<<"*****MAIN--AFTER*****"<<endl;
  19. cout<<"str=" <<str<<endl;
  20. cout<<"*str=" <<&str<<endl;
  21. return 1;
  22. }

执行结果:(打印的输出的时候,有点错误,*str应该为 &str)

    从结果中发现,并未达到改变值得效果,为什么?这个测试代码和本文开始的疑问是一样的,那就进一步分析:
    
    传入值的各变量的初始状态(地址状态):
     
   执行赋值操作

  1. name="alter";
    系统首先需要给字符串“alter”分配内存空间(地址),然后指针才指向其地址。
       
 
 所以*str并没有发生变化,因此最后打印出来的仍是“this is a test”,这也解释了我开始时的迷惑!
 
另一种成功传递参数的指针调用方法----指针的指针:

  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 分配内存成功了。
     3、引用传递:

  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. }
一定要记住这种调用方式

  1. swapref(x, y);
形如:int &a=x; //用于引用传递,可以理解为a就是x,x就是a,只不过名字不一样

执行结果:

    这个具体就不分析了,记住引用传递实参和形参是一样的,只是名字不同而已。
 
 
总结:
       本文重点还是在参数传指针方面,指针确实令人头疼,今天遇到了,会出错,弄明白以后,等过段时间,又忘了,又遇到错误,再来看,这样不断反复,希望能不断的提升,对指针的认识不断的加深!
       写了一下午,边琢磨、边参考、边实验,希望对你有用!错误之处敬请见谅!
 

c++中函数参数传递(值传递、指针传递,引用传递)进一步认识的更多相关文章

  1. C语言中函数参数传递

    C语言中函数参数传递的三种方式 (1)值传递,就是把你的变量的值传递给函数的形式参数,实际就是用变量的值来新生成一个形式参数,因而在函数里对形参的改变不会影响到函数外的变量的值.(2)地址传递,就是把 ...

  2. Java 为值传递而不是引用传递

    ——reference Java is Pass by Value and Not Pass by Reference 其实这个问题是一个非常初级的问题,相关的概念初学者早已掌握,但是时间长了还是容易 ...

  3. 【Qt】信号和槽对值传递参数和引用传递参数的总结

    在同一个线程中 当信号和槽都在同一个线程中时,值传递参数和引用传递参数有区别: 值传递会复制对象:(测试时,打印传递前后的地址不同) 引用传递不会复制对象:(测试时,打印传递前后的地址相同) 不在同一 ...

  4. java是值传递,还是引用传递?

    原文地址:http://blog.csdn.net/zxmzfbdc/article/details/5401960  java到底是值传递,还是引用传递?以前国内的java开发者有过很多争论,由于& ...

  5. python关于入参中,传入的是指针还是引用

    偶然看到别人的代码,发现有的会传入参数之后,做一次copy,试验一下,关于入参中,传入的是指针还是引用先说自己的结论:1.如果传入的是简单的类型,那么传入应该是引用的数值,2.假如传入的是df这种类型 ...

  6. C语言中函数参数传递的本质是值传递

    数组名做函数参数进行传递时,实际上是是一份该指针的拷贝. 给形参赋予其他值,并不影响实参的值. 类似于: int *p = a;    //a为数组名 p = b;          //b为数组名 ...

  7. c语言 函数传输传递的三种方式(值、指针、引用)

    本文摘自<彻底搞定c指针> 一.三道考题开讲之前,我先请你做三道题目.(嘿嘿,得先把你的头脑搞昏才行……唉呀,谁扔我鸡蛋?)考题一,程序代码如下:void Exchg1(int x, in ...

  8. java中的参数传递——值传递、引用传递

    参数是按值而不是按引用传递的说明 Java 应用程序有且仅有的一种参数传递机制,即按值传递. 在 Java 应用程序中永远不会传递对象,而只传递对象引用.因此是按引用传递对象.Java 应用程序按引用 ...

  9. java中函数是值传递还是引用传递?

    相信有些同学跟我一样,曾经对这个问题很疑惑.在网上也看了一些别人说的观点,评论不一.有说有值传递和引用传递两种,也有说只有值传递的,这里只说下个人见解 先看一个例子 public class Test ...

随机推荐

  1. Bootstrap学习-其它内置组件

    1.缩略图(一) 缩略图在网站中最常用的地方就是产品列表页面,一行显示几张图片,有的在图片底下(左侧或右侧)带有标题.描述等信息.Bootstrap框架将这一部独立成一个模块组件.并通过“thumbn ...

  2. 内置函数:min 用法

    内置函数:min 用法 源码 def min(*args, key=None): # known special case of min """ min(iterable ...

  3. Python3.6全栈开发实例[012]

    12.输出商品列表,用户输入序号,显示用户选中的商品(升级题) 商品列表: goods = [{"name": "电脑", "price": ...

  4. hdu 4956 Poor Hanamichi BestCoder Round #5(数学题)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4956 Poor Hanamichi Time Limit: 2000/1000 MS (Java/Ot ...

  5. boost之字符串与文本处理

    C++标准库中字符串转数值使用函数atoi(),数值转字符串使用printf系列函数. boost中使用转换函数操作符lexical_cast<>进行转换,实际上是模板函数.自定义类型,要 ...

  6. 2015.6.30 反弹的教训(想做T)

    心路:在6.29号,市场连续大跌!我到6.29号才想到可以做T+0.6.30消息面已经利好(双降准),已经计划做T+0(X先买后卖).  开市大跌至跌停.午后所有股票开始反弹.但是上午跌停时不敢入市, ...

  7. python如何实现多线程

    一个线程就是一个轻量级进程,多线程能让我们一次执行多个线程. python是多线程语言,其内置有多线程工具包 python中GIL(全局解释器锁)确保一次执行单个线程.一个线程保存GIL并在将其传递给 ...

  8. 希望and目标

    软件工程是一门枯燥的课程,这门课我不喜欢上,容易犯困,但就因为如此.我不得不好好的学习,我希望在这门课上.我能将基础学扎实,在实践上可以自己慢慢研究,我的目标不是很远大,学好.学扎实..在这门课上一周 ...

  9. mysql 7.5.8 服务无法启动 服务没有报告任何错误

    你安装的mysql位置不是c盘的话应该出现此问题. 1.打开bin下的mysql_config.pl文件,查找以下几行,把目录改成你安装mysql的目录即可. my $ldata = 'C:/Prog ...

  10. C# 获取MD5值

    class CommonHelper { /// <summary> /// 通过字符串获取MD5值,返回32位字符串. /// </summary> /// <para ...