精华内容
下载资源
问答
  • 原 JS中全局变量作为函数实参传入的问题 2017年08月27日 11:53:31 love2016hy 阅读数:2390 ....

    JS中全局变量作为函数实参传入的问题

    昨天面试时,被问到了以下的JS代码问题,对比两种情况的输出思考为什么会是这样的结果

    第一种情况
    var a=[1,2,3];
    function foo(a){
        a=[4,5,6];
    }
    foo(a);
    console.log(a); // [1,2,3]
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    第二种情况
    var a=[1,2,3];
    function foo(a){
        a.push(4);
    }
    foo(a);
    console.log(a); // [1,2,3,4]
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

        被问的时候也是蒙圈的,回来仔细查了相关资料,总结一下,希望也能帮助到你理解这个问题。

        看以上两种情况,当全局变量作为函数的实参传入函数之后被重新赋值,然而,执行完函数之后全局变量并没有发生改变,这是为什么?

        JS高级程序设计第三版70页有阐述。加上自己的理解总结如下:

        原本的b=a有两种赋值方式,一种是按值,另一种是按引用。
        ECMAScript中所有的参数传递都是按值传递的,也就是说把函数外部的值复制给函数内部的参数,无论是基本类型还是对象类型,实参和形参都会指向不同的内存地址,并且作用域不同,形参的作用域仅仅在函数体内。
        我们看如下代码:

    var a=[1,2,3],
    var b=1;
    function foo(a,b){
        a=[4,5,6];
        b=2;
    }
    foo(a,b);
    console.log(a); // [1,2,3]
    console.log(b); //1;
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

        我们看到全局变量a和b,被作为实参传给形参后,函数体内对变量a、b进行了重新的赋值,但是并没有改变全局变量a、b的值,即说明函数体内的a、b赋值都是对形参的赋值,形参与在函数中声明的变量一样有着相同的性质。

    但是有一种情况比较特殊,但是不会违背参数按值传递的规律。看如下代码:

    var a=[1,2,3];
    function foo(a){
        a.push(4); //调用引用类型方法,改变了形参a,也改变了全局变量a
        console.log(a); // [1,2,3,4] 此时的a是形参变量的值
        a=[5,6,7];      // 形参重新赋值不会改变全局变量a
        console.log(a); // [5,6,7] 形参变量a
    };
    foo(a);
    console.log(a); // [1,2,3,4]
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    再来看如下代码:

    var a=[1,2,3];
    function foo(a){
        a=[5,6,7]; // 形参a被重新赋值,不会改变全局a
        a.push(4); // 此时只改变了形参a,不会改变全局a
        console.log(a); // [5,6,7,4]
    };
    foo(a);
    console.log(a); // [1,2,3]
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

        对引用数据类型,会发现在函数里,形参被赋值之前,对形参调用引用数据类型的属性(或方法)时,不仅会改变形参,还会改变全局变量。这大概是同名形参和全局变量的一种对应吧,通俗解释一下就是只有当你在函数里被重新赋值之后,你才是独立的。而在这之前我们是穿一条裤子的,属性和方法的调用会同时改变我们。
    希望对你有帮助。

    展开全文
  • add_fun(&number1, &number2);
  • [img=https://img-bbs.csdn.net/upload/202009/22/1600746811_795543.png][/img] 代码如上,Regression是被调用函数,但是经过测试,malloc创建的动态数组xx并没有传入,这是什么原因呀
  • 今天遇到了这样一个问题: include<iostream>; using namespace std; class A{ private: int*p; public: A(int n){ p=new int[n];...调用析构函数"<<endl; delete p; ...

    今天遇到了这样一个问题:

    include<iostream>;
    using namespace std;
    class A{
    private:
        int*p;
    public:
        A(int n){ p=new int[n]; };
        ~A(){
            cout<<"调用析构函数"<<endl;
            delete p;
        }
    
    };
    void Fuc(A a){
        cout<<"进入函数Fuc"<<endl;
    }
    
    int main(){
        A a(5);
        Fuc(a);
    	return 0;
    }
    

    使用的是CLion书写编译的。
    输出窗口报错:

    进入函数Fuc
    调用析构函数
    调用析构函数
    test(12153,0x1198035c0) malloc: *** error for object 0x7fe295400620: pointer being freed was not allocated
    test(12153,0x1198035c0) malloc: *** set a breakpoint in malloc_error_break to debug

    设置断点后发现,类A的对象a在Fuc结束后析构了一次,在main函数return 0;的时候又析构了一次。
    我当时的问题是:a的生存周期不应该是整个main函数吗?a作为实参传入Fuc,Fuc应该是复制一份来使用,不应该在Fuc结束了之后直接把main里的a析构了呀?
    问同学后发现了错误。先附上解决方案:

    #include<iostream>
    using namespace std;
    class A{
    private:
        int*p;
        int l;
    public:
        A(int n){
            p=new int[n];
            l=n;
            cout<<"构造"<<endl;
        };
        A(const A& C){
            cout<<"拷贝函数"<<endl;
            p = new int[C.l];
            l=C.l;
            int i;
            for(i=0;i<l;i++){
                p[i]=C.p[i];
            }
        }
        ~A(){
            cout<<"调用析构函数"<<endl;
            delete p;
        }
    
    };
    
    void Fuc(A a){
        cout<<"进入函数Fuc"<<endl;
    }
    int main(){
        A a(5);
        Fuc(a);
    
    }
    

    输出:
    构造
    拷贝函数
    进入函数Fuc
    调用析构函数
    调用析构函数
    Process finished with exit code 0

    解决的方法就是写一个拷贝函数(构造函数的重载)。

    “问题源于没有重写拷贝函数,类的内部变量如果只是int,char等的基本类型那么编译器可以自动写拷贝函数,但是int *是数组还是指向int的指针无法被编译器识别,所以必须自己写拷贝函数 。 在没有拷贝函数的情况下,编译器无法复制这个类所以那个func就没有复制。”

    感谢跑的飞快的田学长!?

    展开全文
  • 当tmp作为实参传入function函数时,程序会在内存中开辟一段新的空间,在这段内存中定义一个exp变量,然后把tmp的值赋值给exp,由于tmp是一个空指针,并没有内存空间,所以在function函数中对exp的操作并不会对tmp...

    先看一段代码:

    void function(int * exp)
    {
         .............
    }
    
    int main(int argc ,char * argv[])
    {
        int *tmp = NULL;
        
        function(tmp);
    
        .........
        return 0;
    }
    

    笔者测试过,无论在function中怎么最tmp进行操作,都不会改变tmp为NULL的情况。原因是tmp是实参,exp是形参,即使是指针也不会改变这个事实,形参与实参最明显的区别就是作用域和生命周期不同。

    tmp的作用域:在整个main函数中。

    exp的作用域:在function函数中。

    tmp的生命周期:从这个变量被定义到main函数执行完毕。

    exp的生命周期:当funtion函数被调用到function函数执行完毕。


    当tmp作为实参传入function函数时,程序会在内存中开辟一段新的空间,在这段内存中定义一个exp变量,然后把tmp的值赋值给exp,由于tmp是一个空指针,并没有内存空间,所以在function函数中对exp的操作并不会对tmp做出任何改变,当function函数执行完毕后,系统回收这样一段内存,对exp的所有操作都会消失(如果用malloc函数给exp分配了内存空间,这段内存空间会失去控制)。

    如果这段代码是这样:

    void function(int * exp)
    {
         .............
    }
    
    int main(int argc ,char * argv[])
    {
        int tmp_value = 2018;
        int *tmp = &tp_value;
        
        function(tmp);
    
        .........
        return 0;
    }

    这样,tmp指向了具体的内存空间,在function函数中,对 *exp进行赋值等操作是直接会改变*tmp的值(也就是tmp_value的值),但是如果改变了exp指向的内存空间,然后再对exp进行猛操作,便不会影响tmp,但是这样会使得程序不受控制,是不安全的。

    以上是笔者自己的体会,如有错误,希望指出,共同学习进步。


    展开全文
  • def do_ntimes(fuct,n=1): for i in range(n): print(i) do_ntimes(print('help me!'),5) ...1 do_ntimes()函数开始运行 得到这个函数的地址,然后开始接受参数 2 func参数的实参是一...
    def do_ntimes(fuct,n=1):
        for i in range(n):
            print(i)
    
    do_ntimes(print('help me!'),5)

    输出 :

    help me!
    0
    1
    2
    3
    4

    过程是

    1 do_ntimes()函数开始运行 得到这个函数的地址,然后开始接受参数 

    2 func参数的实参是一个函数 发现这一点后运行一遍这个函数,得到返回值 (第一个 help me !就是这个来的)

    3运行for循环  

    之所以后面除了下标 啥都没有是因为函数的返回值是None

     

    想达到效果可以这样 

    def test():return 'help  me !'
    
    def do_ntimes(fuct,n=1):
        for i in range(n):
            print(fuct)
    
    do_ntimes(test(),5)
    
    help  me !
    help  me !
    help  me !
    help  me !
    help  me !

     

    转载于:https://www.cnblogs.com/yuanji2018/p/9145865.html

    展开全文
  • 一、函数的执行符 在JavaScript中函数的执行符() 没有小括号则函数名其实就是一个变量,加上小括号则函数会被执行 var test=function(){ return"HelloWorld"; } alert(test);//结果为function(){return"HelloWorld...
  • c++:函数调用作为实参

    2019-07-16 00:40:49
    在coursera结课习题遇到下面程序,需要将函数作为实参传入。相应的函数声明时,需要注意函数的返回值,函数的形参表。 #include <iostream> using namespace std; int sum(int a[], int n, int (*sqr)(int))...
  • 函数实参和形参、作为值的函数

    千次阅读 2019-01-01 22:41:13
    JavaScript中的函数定义并未指定函数形参的类型,函数调用也未对传入实参值做任何类型检查。实际上,JavaScript函数调用甚至不检查传入形参的个数。 可选形参 当调用函数的时候传入实参函数声明时指定的...
  •     在C++中,定义函数时可以给形参指定一个默认的值,这样调用函数时如果没有给这个形参赋值(没有对应的实参),那么就使用这个默认的值。也就是说,调用函数时可以省略有默认值的参数。如果用户指定了参数的...
  • 最近讨论了一个关于二维数组做为实参传入函数中,可以定义函数形参的方法,觉得收获挺大,总结如下: 开始时,讨论了几种方法: 1、直接用二维数组的形式,如:int array[3][4]。 2、用指向数组的指针,...
  • 在讨论函数时,经常使用的术语实参(argument)和形参(parameter)几乎可以互换,就好像它们是差不多是同一种事物。 1.形参是我们定义函数时所... //performAction传入的两个参数是ninja和'skulking'是函数实参 r...
  • python函数参数改不改变的问题前几天在做项目的过程中发现了一个问题,向函数传入一个list,在函数体内将其赋值给list,对list1操作后发现list也发生了变化,啊 ! 出乎意料。查了一下原因,原来python里有可变...
  • 其中 {1,2,3,4,5} 会分别传给s2[0]、s2[1]、… 、s2[4]的构造函数classname(int val) 作为实参。 3、在堆上定义单个类对象: 如 3、classname* s3 = new classname (5);其中 5 会传给构造函数classname(int val) ...
  • JavaScript学习——函数实参和形参

    千次阅读 2017-09-18 00:13:27
    JavaScript函数实参和形参 在《JavaScript权威指南》中有这样一句话: JavaScript函数是参数化的:函数的定义会包括一个称为形参(parameter)的标识符列表,这些参数在函数体中像局部变量一样工作。函数调用会为...
  • javascript函数内设置传入参数对象导致函数外的实参被修改 问题代码如下 var time=new Date(); console.log(time.getDate()); function set(Time) { Time.setDate(1); } set(time); console.log(time.getDate()...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 50,372
精华内容 20,148
关键字:

函数作为实参传入