C/C++,Java,和Javascript 值传递和引用传递的那点事

首先说说二者到底都是什么?

        引用传递和值传递都是基于传参而言的。

值传递:将实参变量的值复制一份交给形参,即,现在有两个空间,实参空间和形参空间,两空间独立。值传递基本类型的变量而言。

引用传递:是对于对象型变量而言的,传递的是该变量的地址,不是对象本身。


目录

对于C语言 / C++来说

对于Java来说

对于JavaScript来说


对于C语言 / C++来说

值传递:

#include <stdio.h>

void exchange(int a, int b) {
	int c;
	c = a;
	a = b;
	b = c;
}

int main() {
	int a = 5;
	int b = 8;
	exchange(a, b);
	printf("a = %d\n", a);
	printf("b = %d", b);
}

输出结果

执行exchange函数的时候,将实参a和b的值传递给了形参,就是,将a和b的值各复制一份赋值给形参a和形参b的空间,所以,函数内对形参空间的操作完全不会影响到实参空间!而伴随着函数调用的结束,形参空间和其内的局部变量将会被释放。

引用传递:

C语言没有引用传递,看到很多博文都错把指针传递当做引用传递,只有C++中才存在引用传递

#include <iostream>
 
using namespace std;
 
int main()
{
    void fun(int x,int y);        // C++值传递
    void fun1(int& x,int& y);     // C++引用传递

    int x=1,y=2;
    fun(x,y);
    cout<<x<<endl<<y<<endl;

    fun1(x,y);
    cout<<x<<endl<<y<<endl;

    return 0;
}

void fun(int x,int y){
    x=3;
    y=4;
}

void fun1(int& x,int& y){
    x=5;
    y=6;
}

运行结果 

引用传递的形参加了一个&符号,这个形参相当于实参的一个别名,对形参的操作都相当于对实参的操作。 

指针传递:也称地址传递

#include <stdio.h>

void exchange(int *a, int *b) {
	int c;
	c = *a;
	*a = *b;
	*b = c;
}

int main() {
	int a = 5;
	int b = 8;
	exchange(&a, &b);
	printf("a = %d\n", a);
	printf("b = %d", b);
}

运行结果

很明显,指针传递(地址传递)和引用传递(C++)才能改变实参的值,值传递无法改变实参的值

 对于Java来说

Java中参数是用何种传递呢?举个例子,还是两个数交换

值传递

public static void exchange(int a, int b) {  
      int tmp = a;  
      a = b;  
      b = tmp; 
}  
 
public static void main(String[] args) {  
      int a = 3;  
      int b = 4;  
      exchange(a, b);  
      System.out.println(a);  
      System.out.println(b); 
}  

运行结果

3
4

方法调用时,实参把它的值传递给对应方法的形参,同时内存空间中分配了形参空间,接着在方法内对形参空间进行操作。

值传递类型:八种基本数据类型和String

引用传递


public static void main(String[] args) {
	MyClass myClass = new MyClass();
	change(myClass);
	System.out.println(myClass.val);
}
 
private static void change(MyClass myClass) {
        myClass = new MyClass();
	myClass.val = 2;
}

public static class MyClass{
	int val = 1;
}

运行结果:

1

我们将myClass作为实参传入方法的时候,JVM会新申请出一个空间作为形参空间,此时实参myClass和形参myClass指向同一个空间,这时对形参的指向发生改变,故不会影响实参的值。倘若,change方法中去掉new,那运行结果就必然为2了。

对于JavaScript来说

值传递

function fun(val) {
    val++;
    console.log("fun:", val);
}

var a = 20;
fun(a);
console.log("外部:", a);

运行结果

 

将a复制一份传递给val空间,fun函数对val空间进行操作,对形参的改变不会影响到实参

引用传递

function fun(obj) {
    obj.val = 99;
    console.log("fun:", obj);
}

var a = new Object();
fun(a);
console.log("外部:", a);

运行结果:

 

恩,a和obj两个空间都指向(引用)一个空间,故,对obj的操作会影响到a

很多人由此认为:这是引用传递,在局部域(形参)修改对象,会影响到实际域(实参)。

但!

请先看这样一个例子

var fun = function (obj) {
	obj.val = 99;
	obj = {
		val : 123,
	};

	return obj;
}
var object = {
	val : 10,
};

var o = fun(object);
console.log("object:", object);
console.log("o:", o);

运行结果:

不是引用传递嘛?为什么外部域没发生改变呢?

程序是这样运行的: 

将对象object作为实参传递给形参obj,其实传递的是对象object的首地址

函数将对象首地址复制一份传递给形参后,由函数对形参空间进行操作,在程序中,我们能看出:

函数对形参所指的空间的val进行++操作后改变了obj的指向,现在obj指向一个空间,其val = 123;

所以,在JavaScript来说,引用传递的本质还是值传递,其传递的是对象的地址值! 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值