值传递和引用传递是什么?

  • Post author:
  • Post category:其他




值传递


值传递

(pass by value)是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。这种复制一份进行传递的方式叫值传递。



引用传递


引用传递

(pass by reference)是指在调用函数时将实际参数的地址直接传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。所以只有你传的是实际地址,才会修改实际地址!你只要是复制的入参值或者地址,复制的那份在内存中的地址永远不是原地址!SO!

哦!又是一个小小的细节!通过复制的传值方式叫值传递,通过地址直接传递的方式叫做引用传递,那么严格来讲,不论是JAVA还是GO都是对参数进行复制后进行的传递,即JAVA和GO中只有值传递,因为传递的是复制的值或者复制的引用!不存在不复制直接进行地址传递的事情!


一些人的误解,说明!


引用传递中并不存在复制这个过程!所以如果你讲过下面这几句话,那肯定都是错误的:

1.值传递和引用传递,区分的条件是传递的内容,如果是个值,就是值传递。如果是个引用,就是引用传递。(明显不对,复制没复制压根没提!)

2. Java是引用传递(啊,这!JAVA参数传递的是复制的副本,有复制这个过程是值传递!)

3. 传递的参数如果是普通类型,那就是值传递,如果是对象,那就是引用传递。(还是没提复制Copy这回事!)

本文不讨论求值策略,但还是有人想知道!那就放上来!(仅严格求值)

传值调用(值传递)

先对参数进行求值,然后Copy一份值,将copy的这一份值给方法或者函数的入参!所以说值是可以直接赋值的!【狗头】

传引用调用(引用传递)

传一个引用,那就直接引用就完事!通过引用修改值,值会被改变,这个大家没有意见吧!

传共享对象调用(共享对象传递)

传共享对象,先获取到实际传入参数的地址,然后将其复制一份给形参,引用的引用,或者指针的指针,指向的最终还是实际的值!你引用几次都一样!(我猜的【欢迎指正】),所以你要改具体引用地址的值还是可以改!

代码例子:讲实话哦,敲代码真不错!【强行解释】

//GO语言
package main

import "fmt"

func main() {
	//str :=   "123,我们"
	//var stra,strsub = subString(str,0,3)
	//fmt.Println("str的地址:",stra,",str的截取内容:",strsub)
	//调用有返回值的GetA方法,传入a,GO会自动将a的值Copy一份,将copy后的那一份值改变后在GetA方法中传给返回值resultA,所以resultA输出为2
	//参数传递方式和你传什么参数类型没有关系,没有关系,没有关系!
	a := 1
  	var resultA =	GetA(a)
	fmt.Println("resultA的值为:",resultA)
  	//调用无返回值GetB的方法,传入b,GO会自动将b的值Copy一份,将copy后的那一份值改变,这个方法没有返回,所以打印的b的输出没有变化!
	//参数传递方式和你传什么参数类型没有关系,没有关系,没有关系!
  	b:=1
  	GetB(b)
  	fmt.Println("b的值为:",b)
}

//截取字符串
func subString (str string,start int,end int) (*string,string) {
	var s = &str;
	fmt.Println("需要截取的字符串值:",str)
	fmt.Println("需要截取的字符串地址:",&str)
	var subStr = str[start:end]
	return s,subStr
}

//有返回值的,可以改变传入的值并将其返回
func GetA (b int) int {
	b++
	return b
}

//没有返回值,不可以改变传入的值,因为没有任何返回值
func GetB (b int)  {
	b++
}




//JAVA语言
public static void main(String [] args){
int a = 1;
int b = getA(a);
System.out.println(b);
}

public int getA (int b){
	b++;
	return b;
}
此处编译为字节码后此处参数b为1, 直接用1的副本进行计算,为值传递

//截取字符串的方法
public static void main(String [] args){
String  sss =  "123,我们";
String resultS = subString(sss);
System.out.println(resultS );
}


public String subString (String  str){
String strSub = str.subString(0,3);
	return strSub;
}
//strSub输出: 123


小提示:
有兴趣的可以先对JAVA字节码结构进行研究:
JAVA字节码结构组成官方链接:
https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html

总有人说自己English不太行,那就建个生词本,边看官网边记忆生词!因为有点慢,所以缓存一部分生词,直接翻译插件翻译!【狗头】,我English也一般,所以为了看文档,我就在看文档的时候记单词!记忆宫殿不会骗人!可能,也许,大概?


涉及计算机底层虚拟地址和物理地址转换的内容可以看看其他大佬们的文章:
https://zhuanlan.zhihu.com/p/342465996