C语言中的值传参和引用传参是指啥?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言中的值传参和引用传参是指啥?相关的知识,希望对你有一定的参考价值。
在C语言中其实没有引用传参,都是值传参。即传递的都是实参的副本。如下示例,
//交换两个参数的值,值传参
void swap(int x, int y)
int temp = x;
x = y;
y = temp;
int a = 2, b =1;
swap(a,b); //a,b的值不会改变,因为改变的是实参a,b的副本。
另一个示例:
//所谓的“引用传参”,交换两个数值
void swap(int *x, int *y)
int temp = *x;
*x = *y;
*y = tem;
int a =2, b = 1;
swap(&a, &b);//a,b的值改变
其实这里引用传参,传递的也是参数的副本,只是这个副本是变量a,b的地址,所以你在函数swap中你并不能通过参数改变变量a,b的地址,因为它只是一个副本,是值传递。但你得到变量的地址,你就可以访问和改变变量的内容,所以在第二个swap函数中,你可以通过*x和*y来改变实参的值,从而可以达到交换变量a,b值的效果。但这并不是引用传递。只是有这样的说法。推荐你去秒秒学上看看相关的内容,我也是从那上面学来的。 参考技术A
值传递:函数内改变其值,退出函数后值不变
引用传递:函数内改变其值,退出函数后变量值和函数的更改后值一样
代码:
变量 a = M;调用函数A(a);//A函数内部代码为:a =N;
输出 a;
结果:
值传递:M
引用传递:N
js函数传参
也许大家对于函数的参数都不会太在意,简单来说,把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样。深入研究,你会发现其实没那么简单,这个传参是要分俩种情况(其实这是个错误的说法,ECMAScript中所有函数的参数都是按值传递的——《高程3》原话,之所以这里说俩种,是因为结合引用传参更容易理解)—— 值传参和引用传参。
值传参针对基本类型,引用传参针对引用类型,传参可以理解为复制变量值。基本类型复制后俩个变量完全独立,之后任何一方改变都不会影响另一方;引用类型复制的是引用(即指针),之后的任何一方改变都会映射到另一方。
不少人对参数都是按值传递的感到困惑,因为访问变量有按值和按引用两种方式。下面就来看看有何不同:
这一段很重要:我们可以把ECMAScript函数的参数想象成局部变量。在向参数传递基本类型的值时,被传递的值被复制给一个局部变量(即命名参数,或者用ECMAScript的概念来说,就是arguments对象中的一个元素)。在向参数传递引用类型时,会把这个值在内存中的地址(指针)复制给一个局部变量,因此这个局部变量的变化会反映在函数的外部。
1、按值传递
1 function addTen(num) { 2 num += 10; 3 return num; 4 } 5 6 var count = 20; 7 var result = addTen(count); //按值传递 num = count 8 alert(count); // 20, 没变化 9 alert(result); // 30
很好理解,因为是按值传递的,传递完后俩个变量各不相干!
2、按引用传递(这么叫便于理解,其实也是按值传递)
1 function setName(obj) { 2 obj.name = "Nicholas"; 3 } 4 5 var person = new Object(); 6 setName(person); //相当于按值传递 obj = person 7 alert(person.name); // "Nicholas"
当 var person = new Object(); 时,可以用下图表示变量和对象的关系:
当调用函数 setName(person); 时,下图可以表示全局变量person和局部变量obj的关心:
以上代码中创建一个对象,并将其保存在变量person中。然后,这个变量被传递到setName(obj)函数中之后就被复制给了obj。在这个函数内部,obj和person引用的是同一个对象。换句话说,即使ECMAScript说这个变量时按值传递的,但obj也会按引用来访问同一个对象。于是,在函数内部为obj添加name属性后,函数外部的person也将有所反应;因为这时的person和obj指向同一个堆内存地址。所以,很多人错误的认为:在局部作用域中修改的对象会在全局对象中反映出来,就说明参数是按引用传递的。
为了证明对象也是按值传递的,我们再来看看下面这个经过修改的例子:
1 function setName(obj) { 2 obj.name = "Nicholas"; 3 obj = new Object(); //改变obj的指向,此时obj指向一个新的内存地址,不再和person指向同一个 4 obj.name = "Greg"; 5 } 6 7 var person = new Object(); 8 setName(person); //你看看下面,相信我也是按值传递的了吧 9 alert(person.name); //"Nicholas"
当创建obj对象 obj = new Object(); 时,来看看这时person和obj的关系图:
这个例子与前一个唯一的区别,就是setName()函数中添加了两行代码: obj = new Object(); 用来改变obj的指向; obj.name = "Greg"; 用来给新创建的obj添加属性。如果是按引用传递的,那么person就会自动被修改为指向新创建的obj的内存地址,则person的name属性值被修改为"Greg"。但是,当访问person.name时,显示的结果为"Nicholas"。这说明即使在函数内部修改了参数的值,但原始的引用仍然保持未变。实际上,当在函数内部重写obj时,这个变量引用的就是一个局部对象了。而这个局部对象会在函数执行完毕后被立即销毁!
虽然变量person和参数obj的值一样都是同一个对象在内存中的地址,但它们是两个相互独立的变量。如果在函数中改变参数obj的值,使其指向内存中另外一个对象,变量person的值不会改变,还是指向原来的对象。
因此JavaScript中函数的引用类型值参数的传递是按值传递的。
以上是关于C语言中的值传参和引用传参是指啥?的主要内容,如果未能解决你的问题,请参考以下文章