zoukankan      html  css  js  c++  java
  • c++ 中的函数调用中的参数传递

    概述

    初学 (c++),一直搞不懂其参数传递方式。故找到一篇不错的文章:刘志华的深入探讨C++语言中参数传递问题。亲自实践一遍,并作此记录,以加深印象。
     


    主要内容

    本文主要分为五个小部分,下面依次作总结。
     

    简单变量作参数

    简单变量作参数的传递方式是按值传递,在这种传递方式下,在函数体中对形参的修改不会影响实际参数的值,因为它们使用各自的存储空间。

    下面便是一个简单变量作参数的实例。调用 swap 参数同时把 (x) 的值传送给形参 (a),把 (y) 的值传送给形参 (b),在函数体中对形参 (a)(b) 的操作是与对应的实参 (x)(y) 无关的,因为它们使用各自的存储空间。

    void swap(int a, int b)
    {
        int temp = a;
        a = b;
        b = temp;
    }
    int main()
    {
        int x=45, y = 12;
        swap(x, y)
        cout<<"x="<<x<<' '<<"y="<<y<<endl;
        return 0;
    }
    
    

    输出结果是:(x=45,\, y=12). 可见在这种传递方式下,在函数体中对形参的修改不会影响实际参数的值。

    指针作参数

    指针本身是一个变量,特殊之处在于它的值是一个地址,因而可以通过指针来间接访问另外一个内存地址。当函数的形式是指针时,它的实际参数的值必须是一个地址。由于指针作形参,因此对应的形参的实参共用同一个内存单元,形参值的改变将影响实参值。下面继续看一个实例。

    void swap(int* a, int* b)
    {
        int temp = *a;
        *a = *b;
        *b = temp;
    }
    int main()
    {
        int x = 45;
        int y = 12;
        swap(&x, &y);
    
        cout<<"x="<<x<<' '<<"y="<<y<<endl;
    
        return 0;
    }
    

    输出结果是:(x=12,\, y=45). 可见在这种传递方式下,在函数体中对形参的修改将影响实际参数的值。

    引用作参数

    由于引用作形参,因此对应的形参和实参就是同一个内存单元,形参值的改变也将影响实参值。

    void swap(int& a, int& b)
    {
        int temp = a;
        a = b;
        b = temp;
    }
    int main()
    {
        int x = 45;
        int y = 12;
        swap(x, y);
    
        cout<<"x="<<x<<' '<<"y="<<y<<endl;
    
        return 0;
    }
    

    输出结果是:(x=12,\, y=45). 可见在这种传递方式下,在函数体中对形参的修改将影响实际参数的值。

    引用传送的好处是不需要为形参分配新的存储空间,从而节省存储,另外就是如实例这样,能够使对形参的操作反映到实参上。有时,既为了使形参共享实参的存储空间,又不希望通过形参改变实参的值,则应当把该形参说明为常量引用,如:

    void swap(const int& a, const int& b)
    

    在这种情况下,只能读取引用参数 (a)(b) 的值,不能够修改它们的值,因为它们是对应实参的别名,从而杜绝了对实参的有意或无意的破坏。

    数组作参数

    看下面一个实例。

    int sum(int a[], int n)
    {
        int f = 1;
        for (int i=0; i<n; i++)
        {
            f *=a[i];
        }
        return f;
    }
    int main()
    {
        const int N = 6;
        int b[N] = {1,2,3,4,5,6};
    
        int x = sum(b, 6);
        int y = sum(&b[2], 4);
        int z = sum(b+3, 3);
    
        cout<<"x="<<x<<' '<<"y="<<y<<' '<<"z="<<z<<endl;
    
        return 0;
    }
    

    输出结果是:(x=720,\, y=360,\,z=120).
    该函数包含一个主函数和一个 sum 函数,其功能是求出一维整型数组所有元素之积并返回。

    • 在主函数第一次调用 sum 函数时,把数组 (b) 的首地址传送给 (a),把数组 (b) 的长度 (6) 传送给 (n). 执行函数体对数组 (a) 的操作实际上就是对主函数中数组 (b) 的操作,因为它们同时指向数组 (b) 的存储空间;
    • 第二次调用 sum 函数是把数组 (b)(b[2]) 元素的地址传送给 (a), 把整数 (4) 传送给 (n). 执行函数体对数组 (a[n]) 的操作实际上是对数组 (b[2])(b[5]) 之间元素的操作;
    • 第三次调用 sum 函数是把数组 (b)(b[3]) 元素的地址传送给 (a), 把整数 (3) 传送给 (n), 执行函数体对数组 (a[n]) 的操作实际上是对数组 (b[3])(b[5]) 之间元素的操作。

    字符串作参数

    看下面一个实例。

    char* sss(char *sp, char* dp)
    {
        if (*sp == '')
        {
            *dp = '';
            return dp;
        }
        int i=0; // i 是记录 dp 中字符个数
        int j;
        for (char* p=sp; *p; p++)
        {
            //扫描 sp 所指字符串中的每个字符位置
            for (j=0; j<i; j++)
            {
                if (*p == dp[j])
                    break;  // 当 *p 与 dp[0] 至 dp[i-1] 之间的任一元素相同则比较过程结束
            }
            if (j >= i)
                    dp[i++] = *p; // 若 dp 数组的前 i 个元素不等于 *p, 则把 *p 写入 dp[i] 元素中
        }
        dp[i] = ''; // 写入字符串结束符
        return dp;
    }
    int main()
    {
        char a[15] = "abcdeabcde";
        char b[15];
    
        char* c1 = sss(a, b);
        cout<<"c1="<<c1<<' '<<"a="<<a<<' '<<"b="<<b<<endl;
    
        char* c2 = sss(a+4, b);
        cout<<"c2="<<c2<<' '<<"a="<<a<<' '<<"b="<<b<<endl;
    
        return 0;
    }
    

    sss 函数的功能是把 sp 所指向的字符串去掉重复字符后拷贝到 dp 所指向的字符数组中,并返回 dp 指针。在主函数中第一次调用 sss 函数时,分别以 (a)(b) 作为实参,第二次调用时分别以 (a+4) (即 (a[4]) 的地址)和 (b) 作为实参。该程序运行结果是:
    (c1=abcde\,\,a=abcdeabcde\,\, b=abcde)
     
    (c2=eabcd\,\,a=abcdeabcde\,\, b=eabcd)

  • 相关阅读:
    python的正则表达式 re-------可以在字符串前加上 r 这个前缀来避免部分疑惑,因为 r 开头的python字符串是 raw 字符串,所以里面的所有字符都不会被转义
    mysql中max_allowed_packet参数的配置方法(避免大数据写入或者更新失败)
    提交 git 项目 到 github 在 centos 7
    常用正则表达式大全 (转)
    如何让vim编辑器永久显示行号
    Ubuntu下忘记MySQL密码重设方法
    Base64复习
    好用的正则表达式工具
    64位centos下安装python的PIL模块
    springboot中使用servlet通过配置类
  • 原文地址:https://www.cnblogs.com/zhoukui/p/8510782.html
Copyright © 2011-2022 走看看