精华内容
下载资源
问答
  • 函数的参数传递

    2017-07-03 22:43:56
    首先,函数参数传递分为值传递,指针传递和引用传递三种,现阶段常用的是值传递和指针传递。首先说一下值传递,这是一种仅仅传递变量的内容的传递方式,在子函数里不能对上一级函数中对应的变量产生影响,换句话说...

    今天老师讲了函数的调用,也有一些收获。首先,函数的参数传递分为值传递,指针传递和引用传递三种,现阶段常用的是值传递和指针传递。

    首先说一下值传递,这是一种仅仅传递变量的内容的传递方式,在子函数里不能对上一级函数中对应的变量产生影响,换句话说,子函数中接收到的变量实际上是上一级函数中变量的副本。该传递方式过于简单,不贴代码。
    注:值得注意的是,传递二维数组时(见下),是指针传递,在函数内的操作会对上一级函数有影响。

    //题目:编写函数判断一个n阶矩阵是否对称,若对称则返回1,不对称则返回0.
    //主函数中定义矩阵并调用该函数进行判断。
    #include<iostream>
    #include<iomanip>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    using namespace std;
    #define N 88
    int judge(int a[][N],int n)
    {
        for(int i=0;i<n;i++) for(int j=0;j<n;j++) if(a[i][j]!=a[j][i]) return 0;
        return 1;
    }
    int main()
    {
        int n,a[N][N],i,j,k;
        printf("请输入矩阵阶数n:");
        scanf("%d",&n);
        cout<<"请输入矩阵数据:";
        for(i=0;i<n;i++)
        {
            for(j=0;j<n;j++)
            {
                cin>>a[i][j];
            }
        }
        if(judge(a,n)) cout<<"矩阵关于主对角线对称\n";
        else cout<<"矩阵不对称\n";
        return 0;
    }

    然后说一下指针传递,上题的二维数组参数就是指针传递的一种,顾名思义,指针传递后,子函数内接收到的就是一个地址(又称地址变量),所以,上题的二维数组指针传递又可以写成:

    int judge(int *a[N],int n);

    从本质上看,[]和*在某些地方用法相同,可以互相替换。
    但今天的刷题过程中我发现*的优先级低于++,在同时使用时需要加括号,值得注意。例子见下题:

    //设计函数void check(char a[],int *numc,int *numn,int *nume, int *muno)
    //用于统计字符串a中字母、数字、空格和其它字符的个数;设计主函数输入字符串并输出上述统计结果。
    #include<iostream>
    #include<iomanip>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    using namespace std;
    void check(char a[], int *numc, int *numn, int *nume, int *muno);
    int main()
    {
        char a[10000];
        int space=0,num=0,lett=0,othe=0;
        cout<<"输入字符串,以换行符结束:";
        cin.getline(a,9999,'\n');
        check(a,&lett,&num,&space,&othe);
        printf("字母%d个\n数字%d个\n空格%d个\n其他%d个\n",lett,num,space,othe);
        return 0;
    }
    void check(char a[], int *numc, int *numn, int *nume, int *muno)
    {
        for(int i=0;a[i]!='\0';i++)
        {
            if(a[i]==' ') (*nume)++;
            else if((a[i]>='a'&&a[i]<='z')||(a[i]>='A'&&a[i]<='Z')) (*numc)++;
            else if(a[i]>='0'&&a[i]<='9') (*numn)++;
            else (*muno)++;
        }
    }

    最后一种为引用传递(作用和指针没什么大的区别),就是形式有些不同。但引用传递传过来的是变量,且就是主函数中对应的变量,因此,对子函数中的变量修改会影响到主函数。

    void cal(int &a,int &b)    //子函数声明
    cal(x,y)      //主函数调用
    展开全文
  • 函数的参数作为引用 Python 唯一支持的参数传递模式是共享传参(call by sharing)。...”这么说没错,但是会引起误解,因为在旧式语言中,最常用的参数传递模式按值传递(函数得到参数的副本)和按引...

    函数的参数作为引用

    Python 唯一支持的参数传递模式是共享传参(call by sharing)。共享传参指函数的各个形参获得实参中各个引用的副本。也就是说,函数内部的形参是实参的别名。

    解释 Python 中参数传递的方式时,人们经常这样说: “参数按值传递,但是这里的值是引用。”这么说没错,但是会引起误解,因为在旧式语言中,最常用的参数传递模式有按值传递(函数得到参数的副本)和按引用传递(函数得到参数的指针)。

    在Python 中,函数得到参数的副本,但是参数始终是引用。因此,如果参数引用的是可变对象,那么对象可能会被修改,但是对象的标识不变。此外,因为函数得到的是参数引用的副本,所以重新绑定(相当于重新赋值)对函数外部没有影响。

    t1 = [1, 2, 3]

    def foo(f):

        print(id(f))  # 139801222710408

        f = [1, 2, 3]

        print(id(f))  # 139801222747464

        f[1] = 10

    print(id(t1))  # 139801222710408

    foo(t1)

    print(t1)  # [1, 2, 3]

    深刻理解 函数的参数传递是引用的一个副本

    下面我们使用weakref弱引用来观察变量的释放情况。

    import weakref

    def destroy_var():

        print('variable destroy lol.')

    class Mylist(list):

        pass

    a1 = Mylist([1, 2, 3])

    weakref.finalize(a1, destroy_var)

    print(a1)

    a1 = Mylist([2, 3])

    print(a1)

    print('new line --------------------')

    b1 = Mylist([4, 5, 6])

    weakref.finalize(b1, destroy_var)

    def foo(f):

        print(f)

        f = Mylist([5, 6])

        print(f)

    foo(b1)

    上面的打印如下:

    针对a1生命周期如图:

    首先数组对象开辟一块内存保存数据,然后变量a1指向这个地址。当a1重新绑定后,就会把原来的指向地址连接断开来指向新的地址。这样的话,原来的数组对象由于没有引用关系(引用计数为0),就会被销毁。

    根据上面打印的结果,在变量重新赋值的时候就打印了destroy,表示对象已经被销毁了。

    针对b1的生命周期如图:

    首先数组对象[4,5,6]开辟一块内存保存数据,然后变量b1指向这个地址。当把变量b1传给函数foo()的时候,函数foo的形参值其实就是实参b1的一个引用的副本(b1')。因为b1'是一个引用的副本,所以在函数里面我们给这个变量重新赋值并不会销毁原来的对象[4,5,6]。

    根据上面打印的结果,如果不是一个引用的副本,则在重新的赋值的时候就应该打印destroy而不是在脚本执行完毕的时候打印。

     

    不要使用可变类型作为参数的默认值

    class HauntedBus:

        def __init__(self, passengers=[]):

            self.passengers = passengers

        def pick(self, name):

            self.passengers.append(name)

    h1 = HauntedBus()

    h1.pick('zhexiao')

    print(h1.passengers)  # ['zhexiao']

    h2 = HauntedBus()

    print(h2.passengers)  # ['zhexiao']

    不为 HauntedBus 指定乘客的话,self.passengers 变成了 passengers 参数默认值的别名。出现这个问题的根源是,默认值在定义函数时计算(通常在加载模块时),因此默认值变成了函数对象的属性。如果默认值是可变对象,修改了它的值,那么后续的函数调用都会受到影响。

    可变默认值导致的这个问题说明了为什么通常使用 None 作为接收可变值的参数的默认值。

    防御可变参数

    如果函数接收一个字典,而且在处理的过程中要修改它,那么这个副作用要不要体现到函数外部?

    下面的例子可以看到,我们的类把外部传入的实参也进行了修改:

    class HauntedBus:

        def __init__(self, passengers=None):

            if passengers is None:

                self.passengers = []

            else:

                self.passengers = passengers

        def drop(self, name):

            self.passengers.remove(name)

    users = ['zhe', 'xiao']

    h1 = HauntedBus(users)

    h1.drop('zhe')

    print(h1.passengers)  # ['xiao']

    print(users)  # ['xiao']

    其实最好的做法是:类自己维护一个可变列表,将内部的列表与外部传入的实参列表区分开。下面我们用list函数创建 passengers 列表的副本,这样即使类的内部对self.passengers有修改也不会影响外部的列表参数users。

    def __init__(self, passengers=None):

        if passengers is None:

            self.passengers = []

        else:

            self.passengers = list(passengers)

    除非这个方法确实想修改通过参数传入的对象,否则在类中直接把参数赋值给实例变量之前一定要三思,因为这样会为参数对象创建别名。如果不确定,那就创建副本。

     

    变量保存的是引用 总结

    变量保存的是引用,这一点对 Python 编程有很多实际的影响:

    1. 简单的赋值不创建副本。

    2. 对 += 或 *= 所做的增量赋值来说,如果左边的变量绑定的是不可变对象,会创建新对象;如果是可变对象,会就地修改。

    3. 为现有的变量赋予新值,不会修改之前绑定的变量,这叫重新绑定。现在变量绑定了其他对象。如果变量是之前那个对象的最后一个引用,对象会被当作垃圾回收。

    4. 函数的参数以别名的形式传递,这意味着,函数可能会修改通过参数传入的可变对象。这一行为无法避免,除非在本地创建副本,或者使用不可变对象。

    5. 使用可变类型作为函数参数的默认值有危险,因为如果就地修改了参数,默认值也就变了,这会影响以后使用默认值的调用。

    在 CPython 中,对象的引用数量归零后,对象会被立即销毁。如果除了循环引用之外没有其他引用,两个对象都会被销毁。

    展开全文
  • python中函数传递参数有四种形式 fun1(a,b,c) fun2(a=1,b=2,c=3) fun3(*args) fun4(**kargs) 四种中最常见是前两种,基本上一般点教程都会涉及,后两种一般很少单独出现,常用在...

    python中函数传递参数有四种形式

    fun1(a,b,c)
    fun2(a=1,b=2,c=3)
    fun3(*args)
    fun4(**kargs)

    四种中最常见是前两种,基本上一般点的教程都会涉及,后两种一般很少单独出现,常用在混合模式中

    第一种 fun1(a,b,c)是直接将实参赋予行参,根据位置做匹配,即严格要求实参的数量与行参的数量位置相等,比较一般,大多数语言常用这种方式。

    第二种 fun2(a=1,b=2,c=3)根据键值对的形式做实参与行参的匹配,通过这种式就可以忽略了参数的位置关系,直接根据关键字来进行赋值,同时该种传参方式还有个好处就是可以在调用函数的时候作为个别选填项,不要求数量上的相等,即可以fun5(3,4)来调用fun2函数,这里关键就是前面的3,4覆盖了原来a、b两个行参的值,但c还是不变采用原来的默认值3,这种模式相较第一种更加灵活,不仅可以通过fun6(c=5,a=2,b=7)来打乱行参的位置,而且可以在但没有对应行参传递的时候常用定义函数时的默认值。

    第三种 fun3(*args),这传参方式是可以传入任意个参数,这些若干参数都被放到了tuple元组中赋值给行参args,之后要在函数中使用这些行参,直接操作args这个tuple元组就可以了,这样的好处是在参数的数量上没有了限制,但是因为是tuple,其本身还是有次序的,这就仍然存在一定的束缚,在对参数操作上也会有一些不便

    第四种 fun4(**kargs)最为灵活,其是以键值对字典的形式向函数传参,含有第二种位置的灵活的同时具有第三种方式的数量上的无限制。此外第三四种函数声明的方式前的’*’,与c里面的指针声明一样,这里仅做声明标识之用

    最后要强调的是四种传递方式混合使用(大多数情况是这种),fun7(a,b,*c,**d),但四种方式混用时要遵守:

    • args = 须在args之后
    • *args须在args=value之后
    • **kargs须在*args之后

    赋值过程为:

    1. 按顺序把传给args的实参赋值给对应的行参
    2. args = value 形式的实参赋值给行参
    3. 将多余出的即键值对行后的零散实参打包组成一个tuple传递给*args
    4. 将多余的key=value形式的实参打包正一个dicrionary传递给**kargs
    举例

    定义

    def test(x,y=5,*,**b):
    >>>>print x,y,a,b

    调用结果

    test(1) ===> 1 5 () {}
    test(1,2) ===> 1 2 () {}
    test(1,2,3) ===> 1 2 (3,) {}
    test(1,2,3,4) ===> 1 2 (3,4)
    test(x=1) ===> 1 5 () {}
    test(x=1,y=1) ===> 1 1 () {}
    test(x=1,y=1,a=1) ===> 1 1 () {'a':1} test(x=1,y=1,a=1,b=1) ===> 1 1 () {'a':1,'b':1}
    test(1,y=1) ===> 1 1 () {}
    test(1,2,y=1) ===> 出错,说y给赋了多个值
    test(1,2,3,4,a=1) ===> 1 2 (3,4) {'a':1}
    test(1,2,3,4,k=1,t=2,o=3) ===> 1 2 (3,4) {'k':1,'t':2,'o':3}

    转载于:https://www.cnblogs.com/youzizz/p/9869583.html

    展开全文
  • 在c++中,常用的参数传递方式有三种:(1)值传递;(2)地址传递;(3)引用传递。 (1)值传递 按值传递的过程为:首先计算出实参表达式的值,接着给对应的形参变量分配一个存储空间,该空间的大小等于该形参...

    在c++中,常用的参数传递方式有三种:(1)值传递;(2)地址传递;(3)引用传递。

    (1)值传递

    按值传递的过程为:首先计算出实参表达式的值,接着给对应的形参变量分配一个存储空间,该空间的大小等于该形参类型的,然后把以求出的实参表达式的值一一存入到形参变量分配的存储空间中,成为形参变量的初值,供被调用函数执行时使用。这种传递是把实参表达式的值传送给对应的形参变量,故称这种传递方式为“按值传递”。

    实参(argument):传递给函数的值;形参(parameter):用于接受并传递值的变量。

    在值传递的过程中,改变的是形参,实参的值不会发生变化,即无论形参的值被如何赋值,实参都不受影响。

    (2)地址传递

    通过访问地址的形式进行值的传递,该过程为:将值直接赋给指向某一变量地址的指针,从而改变内存地址中存储的值。

    (3)引用传递

    引用传递方式是在函数定义时在形参前面加上引用运算符“&”,我们都知道&为取址符,即获取变量的地址,直接改写地址中存储的值。



    展开全文
  • python中函数定义参数有四种形式: def fun1(a,b,c): pass def fun2(a=1,b=2,c=3): pass def fun3(*args): pass def fun4(**kargs): pass 四种中最常见是前两种,基本上一般点教程都会涉及,后两种一般很少...
  • Python中函数传递参数有四种形式 fun1(a,b,c) fun2(a=1,b=2,c=3) fun3(*args) fun4(**kargs) 四种中最常见是前两种,基本上一般点教程都会涉及,后两种一般很少单独出现,常用在混合模式中 第一种 fun1(a,b,c)...
  • 1. 传递结构成员 2. 传递结构 优点:函数处理是原始数据副本,保护了...缺点:无法保护数据,函数操作可能会意外影响原结构中数据(可以定义成const类型,防止改动) 程序员为了追求效率,常用此方案。
  • 前言 本文主要给大家介绍了关于Golang参数传递的相关内容,分享出来供大家参考学习,下面话不多说了,来...经测试引申出来,当参数变量为指针或隐式指针类型,参数传递方式也是传值(指针本身的copy) Slice是最常用的
  • python 参数传递

    2019-08-12 00:21:50
    ”这么说没错,但是会引起误解,因为在旧式语言中,最常用的参数传递模式 按值传递(函数得到参数的副本)和按引用传递(函数得到参数的指针)。在 Python 中,函数得到参数的副本,但是参数始终是引用。因此,...
  • Python函数位置参数

    千次阅读 多人点赞 2019-07-02 18:25:02
    使用位置参数传递实参情况下,要求缺省值参数放在无缺省值参数后面,如果某个缺省值参数需要使用位置参数方式传递非缺省值,则需要确保该参数前面所有参数都实参传入。 具体内容可参考《第5章函数...
  • C++类模板对象做函数参数 学习目标: * 类模板实例化出对象,向函数传参的方式 一共三种传入方式: 1.指定传入类型 ----直接显示对象数据类型(常用) 2.参数模板化 —将对象中参数变为模板进行传递 3....
  • Kotlin常用高阶函数

    千次阅读 2018-04-11 18:56:07
    高阶函数可以把函数作为参数传递或者返回值返回的函数。既然函数对象作为数值进行传递那么就会如何引用函数的问题。函数引用的三种方式: 直接双冒号的方式,引用的是包级别的函数; // 这种引用适用于...
  • 参数传递中,两个重要的问题必须要明确说明: 1. 当参数个数多于一个时,按照什么顺序把参数压入堆栈; 2. 函数调用后,由谁来把堆栈恢复原状。 C/C++通过函数的调用方式来说明这两个问题的 2、常见...
  • 调用约定的参数传递顺序

    千次阅读 2010-08-06 21:31:00
    都是学习过程中做的笔记。在编程的过程中,函数是必不可少的基础之一。c语言的程序完全由函数构成,所有的代码都在某一个函数中;pascal区分函数和过程,但是本质...在windows平台上常用的函数调用方式有pascal方式(pss
  • $ test$ plusargs和$ value$plusargs ...然而,时候我们在进行仿真时,需要从外部传递参数,这个要求怎么满足呢? 我们来看下 $ test$ plusargs和$ value$ plusargs功能,首先来看一个简单例子: `...
  • ◆当对话框中一个滚动条是,当滚动滚动条时消息控制函数◆ 27 ◆将一个CWnd指针转换成一个控件ID(整数)注意用GetDlgItem()函数是从一个控件ID转换成一个CWnd指针◆ 28 ◆如果在对话框中自定义一个消息方法,...
  • 函数调用方式

    2017-02-22 15:30:49
    调用函数时,计算机常用栈来存储传递函数的参数。栈是一种先进后出数据结构,栈一个存储区、一个栈顶指针。栈顶指针指向堆栈中第一个可用数据项(被称为栈顶)。用户可以在栈顶上方向栈中加入数据,这个操作...
  • 调用函数时,计算机常用栈来存储传递函数的参数。 栈是一种先进后出数据结构,栈一个存储区、一个栈顶指针。栈顶指针指向堆栈中第一个可用数据项(被称为栈顶)。用户可以在栈顶上方向栈中加入数据,这个...
  • C语言中回调函数

    2020-12-22 15:21:25
     回调函数是程序中一种常用的函数调用方式。其特点是可以在下层软件模块(宏观上的被调用者)中,调用来自上层的软件模块(宏观上的调用者)中的函数,这和通常的调用顺序是相反的。  程序的调用方式软件模块的...
  • 获取一个流非常简单,以下几种常用的方式获取流. 所有的Collection结合都可以通过stream默认方法获取流; default Stream Stream() Stream接口的静态方法of可以获取数组对应的流。 static Stream of (T…values) ...
  • 调用函数时,计算机常用栈来存储传递函数的参数。 栈是一种先进后出数据结构,栈一个存储区、一个栈顶指针。栈顶指针指向堆栈中第一个可用数据项(被称为栈顶)。用户可以在栈顶上方向栈中加入 数据,这个...
  • 创建自定义类型常见方式,就是组合使用构造函数模式和原型模式。是用来定义引用类型一种默认模式。 构造函数模式用于定义实例属性,而原型模式用于定义方法和共享属性。 结果:每个实例都会自己一份实例...
  • 调用函数时,计算机常用栈来存储传递函数的参数。 栈是一种先进后出数据结构,栈一个存储区、一个栈顶指针。栈顶指针指向堆栈中第一个可用数据项(被称为栈顶)。用户可以在栈顶上方向栈中加入 ...
  • scala之函数进阶

    千次阅读 2019-05-13 15:13:02
    (1)将函数当成参数进行传递 (2)将函数作为返回值 (3)是否其它方式函数变为返回值 (4)匿名函数作为返回值的作用 4.高阶函数的类型判断 5.常用的高阶函数 6.闭包 7.SAM转换:待续 8.Currying 函数...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 428
精华内容 171
关键字:

常用的函数参数传递方式有