概念

   首先从概念上来说一下这几种函数传参方式及区别:
   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. git的安装-环境变量配置

    windows安装git和环境变量配置 2015.10.12 评论(0) 10,729 点此嗨一下 Git是一款免费.开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目. Git是一个开源 ...

  2. mysql大致学习路径

  3. MongoDB学习笔记—概念解析

    Mongo基本概念 下表将帮助您更容易理解Mongo中的一些概念: SQL术语/概念 MongoDB术语/概念 解释/说明 database database 数据库 table collection ...

  4. SUBMIT RM07DOCS【MB51】 获取返回清单,抓取标准报表数据

    *&---------------------------------------------------------------------* *& Report YT_SUBMIT ...

  5. JAVA项目中常用的异常知识点总结

    JAVA项目中常用的异常知识点总结 1. java.lang.nullpointerexception这个异常大家肯定都经常遇到,异常的解释是"程序遇上了空指针",简单地说就是调用 ...

  6. iOS copy 和 mutableCopy 学习

    (参考 iOS 52个技巧学习心得笔记 第二章 对象 , 消息, 运行期)的对象部分 关于Copy  有个经典问题”大部分的时候NSString的属性都是copy,那copy与strong的情况下到底 ...

  7. 请求json和xml数据时的方式

    当请求xml数据时,直接通过NSMutableData接收后解析, NSURL *url = [NSURL URLWithString:PATH]; _receiveData = [[NSMutabl ...

  8. perspective 能玩点什么

    今天看又在看张鑫旭的博客,本来是在玩 transform:Matrix() 的,有讲到单个变化的矩阵设置,但多个变化的就不是那么回事了. 不过这都不是事啦,人生嘛,显然总会有些难关不是轻易能过去的,反 ...

  9. iOS 学习之 UITabBarController

    - (IBAction)btnClick:(id)sender { UITabBarController *tabBarCtrl = [[[UITabBarController alloc] init ...

  10. QGIS3.0.3+Qt5.9+VS2015_x64编译

    QGIS3.0.3+Qt5.9+VS2015_x64编译 参考:https://blog.csdn.net/u010670734/article/details/80241615 https://ww ...