zoukankan      html  css  js  c++  java
  • C/C++中函数参数传递详解

       昨天看了内存管理的有关内容,有一点了解,但不是很深入,发现之前写代码时有很多细节问题没有注意到,只知道这样做可以实现功能,却不知道为什么可以这样,对于采用自己的方法造成的隐患也未知,更不晓得还有其他方法可以实现,我们知道C++强大的一个原因是因为对于一个问题的答案多种解答方法或思路,我想着也许就是它难学的原因。因为你只知道一种或极少数的实现方法,却不知道其他的实现方法,换句话说,就是对这个东西很掌握的不是很透彻,还没彻底弄明白。虽然有时只知道冰山一角也是可以解决问题的,但窥知全貌可以让我们站在更高的角度,这样在遇到问题时的思路或视野不至于狭小和局限。废话扯多了,只是我的一个感想,我也是一个井底之蛙。进入正题。

        C或C++中函数的参数传递包括:值传递、指针传递、引用传递这三种方法,这三种方法在《程序员面试宝典》中说的很明了,这里加上我自己的理解。

        先看源代码,编译环境是vc6.0,因为调试方便。功能是要实现a和b值的交换。

     1 // test.cpp : Defines the entry point for the console application.
     2 //
     3 
     4 #include "stdafx.h"
     5 #include <iostream>
     6 
     7 using namespace std;
     8 
     9 //值传递
    10 void swap1(int p,int q)
    11 {
    12     int temp;
    13     temp=p;
    14     p=q;
    15     q=temp;
    16 }
    17 
    18 //指针传递,函数体内只有指针值的变化
    19 void swap2(int *p,int *q)
    20 {
    21     int temp;
    22     temp=*p;
    23     *p=*q;
    24     *q=temp;
    25 }
    26 
    27 //指针传递,函数体内只有指针的变化
    28 void swap3(int *p,int *q)
    29 {
    30     int *temp;
    31     temp=p;
    32     p=q;
    33     q=temp;
    34 }
    35 
    36 //引用传递
    37 void swap4(int &p,int &q)
    38 {
    39     int temp;
    40     temp=p;
    41     p=q;
    42     q=temp;
    43 }
    44 
    45 int main()
    46 { 
    47     int a=1,b=2;
    48     swap1(a,b);
    49     //swap2(&a,&b);
    50     //swap3(&a,&b);
    51     //swap4(a,b);
    52     cout<<a<<"  "<<b<<endl;
    53     return 0;
    54 }

    共有四个函数,其中有两个是指针传递,但函数体内的实现不一样。下面具体分析

    1.值传递

    swap1函数实现的值传递,值传递传递的是实际参数的一个副本,如果对这句话不理解,那一步步调试看下内存分配情况。

    执行到48行时,a和b的情况如下

    接着进入swap1函数体内,如下所示

    可以看到的是,p和q的地址和a与b的地址不一样,只是把a和b的值拷贝过去了,在swap1中对p和q操作只是对临时分配的栈中内容进行操作,函数执行完后形参就消失了,对原来的a和b不产生任何影响。所以swap1不能完成交换a和b值的功能

    2.指针传递

    swap2和swap3都是指针传递,swap2函数体内交换了p和q指向地址的值,swap3函数体内交换了p和q指向的地址。

    先说swap2,进入swap2函数体内,如下所示

    可以看到,形参指针p和q指向的是a和b的地址,而不是像值传递那样将实参的值拷贝到另外分配的地址中,运行到函数尾时,如下图

    可以看到、指针p和q指向的地址没变,但地址中的值变了,也即a和b地址中的变了,就是a和b的值成功交换,继续调试可以看到正确的结果,如下图

    再来看swap3,swap3运行到函数尾时的情况如下

    可以看到p和q交换了地址,但最后函数执行完后的结果又如下所示

    a和b的值并未交换,这是为什么呢?

    swap3中,形参p和q会保存在栈中,p指向a的地址,q指向b的地址,使用temp指针完成了p和q的地址交换,即p指向b的地址,q指向了a的地址,但a和b地址中的值并未发生变化,这与swap2不同,swap2中是p指向的地址中的值(就是a)与q指向的地址中的值(b)交换,所以swap2执行完后a和b的值是交换了的。

    3.引用传递

    引用传递时,对形参的操作等同于对实参的操作,即传递的不会是实参的副本,而就是实参,进入swap4函数体内如下所示

    看到这个内存分配,很明了了吧。最后会交换a和b的值。

    到此,完了。当然函数参数也可以是指向指针的指针,这也是很常见的,但通常用在需要动态分配内存的地方以避免内存泄露。在使用cuda时调用cudaMalloc其参数就是这样,指向指针的指针。而malloc、CPLMolloc、new这些是通过返回值传递分配的动态内存的,自然是不会出现内存泄露的,这个后面再说。

  • 相关阅读:
    OpenCV 2.4.11 VS2012 Configuration
    [LeetCode] 11. Container With Most Water 装最多水的容器
    Android rxjava2的disposable
    Android在应用设置里关闭权限,返回生命周期处理
    Android 使用greenDAO 3.2.2 操作外部数据库
    Android中intent相关,setFlag(xx);
    Android 关于Acitivity 的setFlag以及launchmode的总结
    GreenDao3.0新特性解析(配置、注解、加密)
    Android RecycleView实现混合Item布局
    Android各大手机系统打开权限管理页面
  • 原文地址:https://www.cnblogs.com/Romi/p/2630014.html
Copyright © 2011-2022 走看看