概念

   首先从概念上来说一下这几种函数传参方式及区别:
   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. 【题解】Journeys(线段树优化连边)

    [#3073. Pa2011]Journeys (线段树优化连边) 这张图太直观了,直接讲透了线段树优化连边的原理和正确性. 考虑建立两颗线段树,一颗是外向树,一颗是内向树,相当于网络流建模一样,我们 ...

  2. 我的Android进阶之旅------>Android关于dp(dip)、sp转px的工具类

    下面是一个工具类,提供了dp.sp.px之间相互转化的方法. import android.content.Context; /** * dp.sp 转换为 px 的工具类<br> * & ...

  3. C#窗口的Load事件与Shown事件的差别

    Load:在第一次显示窗口前发生. <pre name="code" class="csharp"> private void Form1_Load ...

  4. 023-Spring Boot 服务的注册和发现

    一.概述 服务调用 1.1.nginx方式 1.2.注册中心 二.注册中心[zookeeper] 2.1.安装zookeeper3.4.11 2.2.服务提供方,需要在服务启动时吗.,把服务的信息(I ...

  5. redis性能测试以及影响性能的因素

    redis-benchmark测试工具的命令使使用方法及参数如下:redis-benchmark [-h <host>] [-p <port>] [-c <clients ...

  6. self-awareness is key in changing the way you think

    1: controlling the way you think is a manageable process The good news is that you have control over ...

  7. GPS USB驱动串口被占用

    1.一般是装了错误的驱动,显示如下 2.实际装好应该是显示的 3.驱动选择,先卸载了上面的virtual驱动,安装下面箭头指向的驱动 这里的卸载很重要,先点设备管理器的--查看--显示隐藏设备, 然后 ...

  8. JAVA抠取Excel中的图片

    EXCEL中扔了一堆的图片,老大让对应到数据库中的数据上.思路先把图片抠出存成单个图片.然后上传到服务器,取下路径更新到数据库中. 注释掉的部分为有多个Excel时使用. package com.** ...

  9. 分层架构下的纯JDBC事务控制简单解决方案【转】

    http://blog.csdn.net/qjyong/article/details/5464835 对目前的JavaEE企业应用开发来说,基本都会采用分层的架构, 这样可以分散关注.松散耦合.逻辑 ...

  10. $Android AlarmManager的用法详解

    在Android的Alarm机制中,使用AlarmManager可以实现类似闹钟这样的定时任务.在毕业设计项目中要实现定时任务的功能,所以在这里先进行一下梳理. (一)AlarmManager与Bro ...