• C++之参数总结


    函数的形参为函数提供了已命名的局部存储空间,它是在函数的形参表中定义的,并由调用函数时传递给函数的实参初始化,而形参的

    初始化与变量的初始化一样,如果形参具有非引用类型,则复制实参的值,如果形参为引用类型,则它只是实参的别名,具体分析如下:

     

    1.非引用形参

    普通的非引用类型的参数通过复制对应的实参实现初始化,而当实参副本初始化形参时,函数并没有访问所传递的实参本身,因此这不会

    改变实参的值,例如:

    int fun(int v1,int v2)

    {

       while(v2)

        {

          int temp=v2;

         v2=v1%v2;

         v1=temp;

        }

       return v1;

    }

    while循环体虽然修改了v1和v2的值,但是这些改变仅限于局部参数,而对调用fun()函数使用的实参没有任何影响,而一旦函数执行结束,

    这些局部参数(局部变量)的值也就没有了也就是说,假如我们调用了函数:fun(a,b)   则a和b的值不受fun()执行的赋值修改的影响.

    2.指针形参

    与其他非引用类型的形参一样,如果函数的形参是指针,那么此时也将复制实参指针,所以,该类形参的任何改变也仅是作用于局部副本,不过

    由于指针类型与普通变量的差异,在操作上也有点不同,指针实参的局部副本虽然不会改变主调函数使用的实参指针值,但是,如果函数形参是

    非const类型的指针时,则函数可以通过修改指针所指向对象的值来扩大它的影响力。

    例如:

    void reset(int *ptr)

    {

        *ip=0;

         ip=0;

    }

    调用reset()函数后,实参依旧保持原来的值,也就是说它还是指向原来的地方,不过,它所指向的那个地方的对象的值现在变为了0.

    如果需要保护指针所指向的值,则可以将形参定义为指向const对象的指针,如下:

    void fun(const int *ptr)

    {

    ...................................

    }

    此时,我们即可以用int *也可以用const int *类型的实参来调用fun()函数,但是仅可以将int *类型的实参传递给reset()函数

    3.const形参

    如果函数使用的是非引用的非const形参,既然传递的只是实参的副本,当然既可以给该函数传递const实参也可以传递非const形参,如果

    函数使用的是非引用的const类型,如:

    void fun(const int i){

        ..............................

    }

    则在函数中,我们不可以修改实参的局部副本,不过,由于实参仍然是以副本的形式传递的,因此传递给fun()函数的既可以是const

    对象也可以是非const对象

    4.引用形参

    与所有引用一样,引用形参将直接关联到其所绑定的对象,作为实参的别名,而非仅仅是这些对象的副本,因此,我们可以在实际运用中

    通过引用形参让函数修改实参的值,这可以弥补函数只能返回单个值的缺陷,在函数需要返回的值不止一个时,我们可以通过传递额外的

    引用形参来解决该问题。此外,我们还可以利用const引用来避免大型数据的复制,提供效率的同时,也可以保护所指向的对象。

    如果函数具有普通的非const引用形参,则显然是不能通过const对象进行调用的,因为此时函数可以修改传递进来的参数,这样就违背了

    实参的const特性,其实,在这个问题的处理上,C++显得更为严格,也就是说,非const引用形参只能与完全同类型的非const对象所关

    联.

    5.传递指向指针的引用

    void fun(int *&v1,int *&v2)

    {

       int *temp=v2;

       v2=v1;

       v1=temp;

    }

     首先对于形参 int *&v1 我们可以这样理解,从右至左:v1是一个引用,它与指向int型对象的指针相关联,换句话说,v1只是传递

    进fun()函数的任意指针的别名,因此,我们可以通过调用该函数来分别改变他们所指向对象的值。

    6.数组形参

    有三种方式就可以指定数组的形参:

    void fun1(int *)

    void fun2(int [])

    void fun3(int [10])

    这三种方式都是等价的,形参都是int*,这我们可以这样理解:使用数组名字时,数组名会自动转换为指向其第一个元素的指针,通常,将

    数组形参直接定义为指针比使用数组语法定义更好,因为此时函数操作的是指向数组元素的指针,而不是数组本身,此外,编译器会忽略

    为任何数组形参指定的长度,但是往往因为数组越界问题而导致运行失败。

    7通过引用传递数组

    大部分情况下,数组以普通的非引用类型传递时,数组会悄悄地转换为指针,因此,此时函数实质上操作的也是指针的副本,它不会修改

    实参指针的值,但是函数可以通过这些指针改变它所指向的数组元素的值。但是,如果形参是数组的引用如:

    void  fun(int (&arr)[10]){

      ................

    }

    编译器不会将数组实参转换为指针,而是传递数组的引用本身,在这种情况下,数组大小成为形参和实参类型的一部分,编译器将严格检

    查数组实参的大小与形参的大小是否匹配。

     

     

  • 相关阅读:
    @3 UOJ428 & UOJ461 & UOJ671
    DZY Loves Chinese II
    [冲刺国赛2022] 模拟赛12
    [冲刺国赛2022] 模拟赛11
    【记录】将labelme json文件转为mask掩模图
    两阶段深度学习中的两阶段是指什么意思?
    Docker(一)安装、介绍、镜像、容器与仓库
    C++ Primer Plus 学习 (一)C++介绍与数据处理
    C++ 疑问合集
    遇到ImportError: cannot import name ‘soft_unicode’ from 'markupsafe’问题
  • 原文地址:https://www.cnblogs.com/kunhu/p/3609147.html
Copyright © 2020-2023  润新知