-
2021-08-19 09:52:53
SHIT,这都忘了!!那就再来一遍!!
- 实参为基本类型时,对形参的处理不会影响实参。
- 实参为引用类型时,对形参的处理会影响实参。
- String、Integer、Double等immutable类型,因为本身没有提供修改函数的操作,每次操作都是生成一个新对象,所以要特殊对待,可以理解为值传递,形参操作不会影响实参对象。
更多相关内容 -
python 引用传递和值传递详解(实参,形参)
2021-01-20 00:08:06形参当然了就是形式参数,而实参是我们需要给这个函数传入的变量,在我们给实参传入变量之后,调用函数,实参则自动会把数值或则变量赋予形参,从而通过函数得出我们想要的结果。既然形参是由实参赋值传递,所以说... -
关于值传递形参不改变实参原理及如何使用地址传递修改实参
2022-06-15 21:11:16关于值传递形参不改变实参原理及如何使用地址传递修改实参值传递
向函数(形参)中传递的变量(实参)称为值传递,为何修改形参不会改变实参?形参有属于形参的独立的内存地址,在函数体中只会改变形参地址中的值与实参地址无关
例如用a代表形参,b代表实参a=b;//将实参传递给形参 a--;//函数体中形参自减1的操作自然不会影响到实参
虽然a和b的值相同,但在函数体中只会对形参(a)做出改变,与实参(b)无关.
地址传递
顾名思义即向函数中传递内存地址,自然要使用指针接收,因此形参必须为指针变量
形参与实参使用同一个内存地址,对形参进行修改也就等同于对实参修改 -
关于函数调用时候,形参值、传递实参值,的改变问题
2019-09-03 17:49:57实参直接作为参数传递给函数时候,函数会先将形参初始化,将实参的值传递给形参,进入函数里面后,依然是对形参进行修改。调用结束后,实参的值并没有修改 函数原型void function1(int x) {x=5; } int a=0;...void function1(int x) { x=5; } void function2(int *x) { *x=5; } int main() { int a=0; function1(a); //此时a=0 /*因为调用时候,首先是执行int x=a的操作,函数里面依然是对x=5赋值,没有改变a */ function2(&a); //此时a=5 /*因为调用时候,首先是执行int *x=&a的操作,函数里面是对a的地址里面的值修改为5,由于a变量地址是不会变的,所以a地址里存的被修改了,值也被修改了。 */ return 0; }
实参直接作为参数传递给函数时候,函数会先将形参初始化,将实参的值传递给形参,进入函数里面后,依然是对形参进行修改。调用结束后,实参的值并没有修改
函数原型void function1(int x) {x=5; }
int a=0;function1(a)
翻译过程并不是直接把x用a替换,然后a=5,
而是先int x=a=0,然后x=5,这样调用完毕,x释放,但是a的值没有改变。要想改变,可以用指针,
函数原型void function2(int *x) {*x=5;}
int a=0;function1(&a)
翻译过程就是首先将a的地址复制给x,然后*x=5
,就是将这个地址里存的值改为5,因为a的地址不变,所以a的值被修改了 -
使用了指针,但是函数的形参仍然无法传递给实参
2020-06-09 10:25:11请问是为什么啊,然后怎么在这个函数内部能让形参传递给实参呢? ``` #include #include #define MAXSIZE 27/*存储空间初始分配量*/ typedef int ElemType;/*ElemType类型根据实际情况而定,这里假设为int*... -
形参和实参——Java值传递详细说明
2021-06-10 09:48:38java只有值传递,方法上传的是引用对象的地址 因为java中方法的参数传递的原则是复制。也就是说不管是值传递还是引用传递,参数传递的都是值得拷贝或者是引用的拷贝。因此对象作为参数传递的是对象的引用 ...目录
目录
三、基本数据类型、普通对象引用类型、String及基本数据类型装箱类的引用类型---的值传递
2.2其它对象类型 作为形参:(值传递---传递引用的副本,但是在栈stack中 原引用和副本都指向 在 堆heap中同一个实例对象,此时修改实例对象,自然实参的值也就变了)
2.3传递类型是String类型(Integer等基本类型的包装类等同 还是值传递,只不过在处理形参时多了重新赋值引用地址的动作)
一、形参与实参:
形参,是指在定义函数时使用的参数,目的是用于接收调用该函数时传入的参数。简单理解,就是所有函数(即方法)的参数都是形参。
实参,在调用有参函数时,主调函数和被调函数之间有数据传递关系。在主调函数中调用一个函数时,函数名后面括号中的参数称为“实际参数”。public static void main(String[] args) { int num = 3; printVal(num); //这里num是实参 } private static void printVal(int num) { num = 5; //这里num就是形参 }
二、值传递和引用传递
值传递:是指在调用函数时,将实际参数复制一份传递给函数,这样在函数中修改参数时,不会影响到实际参数。其实,就是在说值传递时,只会改变形参,不会改变实参。
引用传递:是指在调用函数时,将实际参数的地址传递给函数,这样在函数中对参数的修改,将影响到实际参数。
那么,我来给大家总结一下,值传递和引用传递之前的区别的重点是什么。
特别强调的是,千万不要以为传递的参数是值就是值传递,传递的是引用就是引用传递。也不要以为传递的参数是基本数据类型就是值传递,传递的是对象就是引用传递。 这是大错特错的。以前的我,一直都是这样认为的,现在想来真是太天真了。判断是值传递还是引用传递的标准,和传递参数的类型是没有一毛钱关系的。
三、基本数据类型、普通对象引用类型、String及基本数据类型装箱类的引用类型---的值传递
概述:
基本数据类型-----形参改变无法改变实参
普通引用类型(对象)-----形参改变,因实参和形参 指向同一个目标对象实例, 因此实参也改变
String以及基本数据类型的装箱类引用类型------形参改变,因实参和形参指向的目标实例对象不一致,因此实参不变
Java的参数传递是值传递,而平常我们在Java中所说的“引用传递”,实际上只是将引用对象的地址拷贝了一份传给形参,而非自己本身的地址,也是值传递;否则,当我们为形参更换引用地址后,原拷贝方引用的地址(即为实参)也会发生变动
区分值传递还是引用传递的关键的确像你所说的,需要看形参是否改变了实参,但对于对象来说,地址才是实参! 值传递:形参改变无法改变实参。
因为java中方法的参数传递的原则是复制。也就是说不管是值传递还是引用传递,参数传递的都是值得拷贝或者是引用的拷贝。因此对象作为参数传递的是对象的引用
2.1基本数据类型作为形参:(值传递)
public class ValueTransmit { public static void main(String[] args){ int no=1; System.out.println("变更前:"+no); addInt(no); System.out.println("变更后:"+no); } public static void addInt(int n){ n=n+1; System.out.println("形参的值:"+n); } } 运行结果: 变更前:1 形参的值:2 变更后:1
说明:调用addInt(no)时,实际参数no,值传递给相应的形式参数n,在执行方法addInt()时,形式参数n的值的改变不影响实际参数no的值,no的值在调用前后并没改变。
可以发现,传递基本数据类型时,在函数中修改的仅仅是形参,对实参的值的没有影响。
需要明白一点,值传递不是简单的把实参传递给形参,而是,实参建立了一个副本,然后把副本传递给了形参。下面用图来说明一下参数传递的过程:
2.2其它对象类型 作为形参:(值传递---传递引用的副本,但是在栈stack中 原引用和副本都指向 在 堆heap中同一个实例对象,此时修改实例对象,自然实参的值也就变了)
public class User { private int age; private String name; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public User(int age, String name) { this.age = age; this.name = name; } public User() { } @Override public String toString() { return "User{" + "age=" + age + ", name='" + name + '\'' + '}'; } }
package com.jokin.learn; import java.util.HashMap; import java.util.Map; public class TestUser { public static void main(String[] args) { User user = new User(18, "zhangsan"); System.out.println("修改对象前:"+user); changeUser(user); System.out.println("修改对象后:"+user); } private static void changeUser(User user) { user.setAge(20); user.setName("lisi"); } }
打印结果:
修改对象前:User{age=18, name='zhangsan'}
修改对象后:User{age=20, name='lisi'}可以发现,传过去的user对象,属性值被改变了。由于,user对象存放在堆里边,其引用存放在栈里边,其参数传递图如下:
user是对象的引用,为实参,然后创建一个副本temp,把它传递给形参user1。但是,他们实际操作的都是堆内存中的同一个User对象。因此,对象内容的修改也会体现到实参user上。2.3传递类型是String类型(Integer等基本类型的包装类等同 还是值传递,只不过在处理形参时多了重新赋值引用地址的动作)
public class TestStr { public static void main(String[] args) { String str = new String("zhangsan"); System.out.println("字符串修改前:"+str); changeStr(str); System.out.println("字符串修改后:"+str); } private static void changeStr(String str) { str = "lisi"; } }
打印结果:
字符串修改前:zhangsan
字符串修改后:zhangsan咦,看到这是不是感觉有点困惑。按照第二种情况,传递参数是引用类型时,不是可以修改对象内容吗,String也是引用类型,为什么在这又不变了呢?
再次强调一下,传递参数是引用类型,并不代表就是引用传递,其实它还是值传递。此时的 lisi 和上边的 zhangsan 根本不是同一个对象。画图理解下:
图中,str是对象 zhangsan 的引用,为实参,然后创建了一个副本temp,把它传递给了形参str1。此时,创建了一个新的对象 lisi ,形参str1指向这个对象,但是原来的实参str还是指向zhangsan。因此,形参内容的修改并不会影响到实参内容。所以,两次打印结果都是zhangsan。
第三种情况和第二种情况虽然传递的都是引用类型变量,但是处理方式却不一样。第三种情况是创建了一个新的对象,然后把形参指向新对象,而第二种情况并没有创建新对象,操作的还是同一个对象。
我们在changeStr 方法中 使用
str = "lisi" ;
试着去更改str 的值,阴差阳错的直接改变了str 的引用的地址。因为这段代码,会new一个String,再把引用交给str,即等价于:str= new String("lishi");
而原来的那个"zhangsan"字符串还是由实参持有着的,所以,并没有修改到实际参数的值。
如果把上边changeUser方法稍作改变,你就会理解:
private static void changeUser(User user) { //添加一行代码,创建新的User对象 user = new User(); user.setAge(20); user.setName("lisi"); }
运行以上代码,你就会惊奇的发现,最终打印修改前和修改后的内容是一模一样的。 这种情况,就等同于第三种情况。因为,这里的形参和实参引用所指向的对象是不同的对象。因此,修改形参对象内容并不会影响实参内容。
修改对象前:User{age=18, name='zhangsan'} 修改对象后:User{age=18, name='zhangsan'}
总结:
从以上三个例子中,我们就能理解了,为什么Java中只有值传递,并没有引用传递。值传递,不论传递的参数类型是值类型还是引用类型,都会在调用栈上创建一个形参的副本。
不同的是,对于值类型来说,复制的就是整个原始值的复制。而对于引用类型来说,由于在调用栈中只存储对象的引用,因此复制的只是这个引用,而不是原始对象。
最后,再次强调一下,传递参数是引用类型,或者说是对象时,并不代表它就是引用传递。引用传递不是用来形容参数的类型的,不要被“引用”这个词本身迷惑了。这就如同我们生活中说的地瓜不是瓜,而是红薯一样。
- 参数传递时,是拷贝实参的副本,然后传递给形参。(值传递)
- 在函数中,只有修改了实参所指向的对象内容,才会影响到实参。以上第三种情况修改的实际上只是形参所指向的对象,因此不会影响实参。
-
深刻理解形参和实参的三种传递方式(值传递,地址传递,引用传递)
2021-05-29 10:36:34文章目录前言一、值传递二、地址传递三、引用传递总结 前言 在主函数实现了解传递的本质。 提示:以下是本篇文章正文内容,下面案例可供参考 一、值传递 在主函数中 #include <iostream> using namespace ... -
老生常谈C++中实参形参的传递问题
2020-12-31 00:19:49这是最普通,也是最简单的形参传递了。 参数传递,即是使用实参副本(注意啊,是副本,不是实参本身)来初始化形参; 因此,在函数体内对形参的修改不会影响实参的值。 如果形参是指针类型的,那么函数体内是否可以... -
c语言的形参和实参传递的区别详解
2020-12-20 21:23:49C语言中实参和形参之间的数据传递是单向的“值传递”,单向传递,只能由实参传给形参,反之不行 输出格式并没有选择%p而是选择了%d,因为十进制的数看起来更直观 1 值传递 如果只是传递值的话: #include //值... -
浅谈c++中形参不能改变实参
2020-04-03 18:48:52c语言我们都知道形参不能改变实参,实参能改变形参,我们能保证自己很熟悉这个概念吗,能不能保证自己每次都不犯错,掉坑里。 #include <iostream.h>...“形参未改变,实参传递给实参的值:... -
python 函数(实参与形参、传递参数)
2020-11-20 22:02:44函数什么是函数?函数是带名字的代码块,用于完成具体的工作。写出一个函数后,就可以一直...即是下一节讲到的形参1 #向函数传递信息23 defgreet_user(username):4 """显示简单的问候语"""5 print("hello," + userna... -
python 引用传递和值传递(实参,形参)
2018-10-08 18:29:32python中函数参数是引用传递(不是值传递)。对于不可变类型,因变量不能被修改,所以运算时不会影响到变量本身;而对于可变类型来说,函数体中的运算有可能会更改传入的参数变量. 形参: 函数需要传递的参数 实参... -
java形参实参传递
2021-02-12 14:06:59Java参数传递(其实java参数传递都是值传递,只不过当参数是对象时,传递的是地址,所以参数是对象时,如果通过形参改变对象内的内容,实参对象的内容也会改变,当对形参重新赋值时,这意味形参指向了别的对象,所以... -
C语言参数传递——实参与形参
2021-02-04 18:18:19在C语言中,关于形参与实参说明...4)对应的实参和形参是两个独立实体,它们之间只有单向的值的传递,即实参的值传递给形参。形参的值在函数中不论怎么改变,都不会影响实参。 以上来自 C语言程序设计(第三版)/杨路. -
关于java中形参值和实参值的总结,什么时候会改变实参值
2020-12-24 21:30:35首先Java里面都是值传递,也就是形参的值改变是不会改变实参的值的。 -
C语言中,如何利用函数和指针变量通过形参变量的值改变实参变量的值
2021-05-22 08:45:47必备知识:c语言中的函数调用和...函数的一个功能就是传递数值进行运算,那么我们如何利用函数和指针变量通过形参变量的值改变实参变量的值呢?首先,让我们先举一个例子。#includeint main(){void func(int a,int ... -
c语言函数的值传递机制(swap函数怎么通过形参改变实参的值)
2021-10-03 20:41:43swap函数中体现出的c语言函数的值传递机制(形参中int * &是什么意思) 目前初学C语言,对于深层内存机制了解不是十分透彻,只是将自己的理解方式简单记录一下。 我们知道交换两个变量的数值非常简单,只需要一... -
Java中形参,实参,值传递,引用传递
2022-04-19 16:01:27Java中形参,实参,值传递,引用传递 学习值传递,和引用传递很容易令人迷糊,那么就来仔细的分析一下。 想明白这个问题首先要知道形参和实参 实参:就是我们要传递给方法的实际参数 形参:就是我们方法签名上... -
形参如何改变实参
2021-12-17 21:34:45形参、实参 -
java形参和实参的三种传递方式(值传递,地址传递,引用传递)
2022-07-11 13:57:42博客博客值传递:对形参的修改不会影响到实参引用传递:对形参的修改会影响实参在主函数中 输出结果为: 因为在int j=i 时,这是一个开辟一个新内存,然后将i中的值复制到j中的过程。所以,j中的值改变不会引起i中... -
形参、实参、引用传递、按值传递
2021-07-21 18:59:55即调用的时候传递给副本形参的值为一个地址; 1、改变形参变量对应的值的会改变实参变量对应的值。 public static void main(String[] args){ List list = new ArrayList<Integer>(); -
形参与实参&值传递和地址传递
2017-06-23 16:40:272、实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值。 3、实参和形参在数量上,... -
函数实参与形参之间的传递
2018-04-13 23:24:25实参是指在函数调用时,必须有确切的值以便赋给形参的一种参数,它可以为常量,变量,表达式,函数等。 形参是在定义函数名和函数体时使用的一种参数,目的是用于接收调用该函数时传递的参数。它只能是变量。 ... -
形参和实参的参数传递
2020-11-23 21:37:09引用类型:设计栈内存和堆内存,形参改变之后会改变堆内存的值,方法使用后从栈内存消失,此时实参也需要调用堆内存中的值,所以形参改变会影响实参的值。 一个就是两个互不关联,另一个是2个方法都调用一个地方的值... -
形参和实参的关系以及值传递问题
2021-11-24 22:24:19方法中形参和实参的关系 要认真体会一下形参和实参的关系,这对初学Java的小白来说至关重要哦! #定义 -
C# 图解形参与实参传递和存储值的方式
2022-07-10 23:37:10当你在调用方法时,系统会通过将实参的值复制到形参的方式,把数据传递给方法。系统会执行如下操作: 在栈中为形参分配空间。 将实参的值复制给形参。 下面以一段代码举例,并说明形参和实参在方法执行的不同阶段在... -
C语言中实参与形参的传递
2019-09-29 18:13:22因为在实参给形参传递的过程中,形参只是实参的一个临时拷贝,一个临时地址,用完自动销毁,如图,可以明显的看出实参a,b和形参x,y的地址明显不同。 第一种方法只是把实参a,b的值传递给形参x,y, 所以形参x,y... -
形参和实参之间的三种传递方式
2021-05-24 07:03:51//形参和实参之间的三种传递方式void fun(int i){ i++;}void fun(int &i){ i++;}void fun(int *i){ *i=*i+1;}若指针指向的是数组的首地址,则数组元素的访问方式1.数组名[i] 指针名[i]2.*(数组名+i) *(指针名+i)... -
形参与实参之间的值传递
2013-10-09 11:45:00C语言中,参数的传递方式是“单向值传递”,形参和实参变量各自有不同的存储单元,被调用函数中的形参变量值的变化不会影响实参变量值。 举个例子 #include<stdio.h> void swap(int x,int y)...