函数传参的类型

2023-08-19 13:12:02 +08:00
 justonelastdance

一般分为值传递和引用传递,大部分语言都是这样吧。 有没有特殊的语言,只有值传递的?

1087 次点击
所在节点    问与答
14 条回复
geelaw
2023-08-19 13:13:37 +08:00
Java 和 C 都只能传值。
geelaw
2023-08-19 13:27:20 +08:00
另外,JavaScript 也只有传值。

对于纯函数式语言来说,传引用和传值没有任何区别。
justonelastdance
2023-08-19 13:30:09 +08:00
@geelaw js 有引用传递吧。传对象和数组就是引用传递
geelaw
2023-08-19 14:02:57 +08:00
@justonelastdance #3 一个方法的一个参数是传引用 (pass by reference) 的含义是:实参可以被赋值,且方法内对形参的赋值会导致对实参赋值。

let a = {};
function b(c) { c.d = 1; c = null; }
b(a);
console.log(a);

这里 a 不是 {} 那个对象,而是对象引用,a 的值引用了那个对象。b(a) 这个调用中:

形参 c 的值是实参 a 的值的副本,故一开始 c 也引用了那个对象,透过 c 的值可以操作那个对象,因此 c.d = 1 这句话会改变那个对象,当然,这没有改变 a ,因为 a 不是那个对象,而 a 还是引用了那个对象。

形参 c 和实参 a 绑定到了不同的存储位置,对 c 的赋值并不影响 a 的值(也就是不影响 a 的值引用了哪个对象),因此 c 是传值。

最简单的理解 JavaScript 的方法是这样的:这个世界上有两种值,对象实例、对象引用,除了 import 带来的,其他所有变量名都指示互不相同的存储位置,且每个具名的存储位置都只能存储对象引用。( 123 这种 typeof 会得到 'number' 的东西直接理解为不可变对象就好,不要搞什么 primitive value 之说。)
justonelastdance
2023-08-19 15:29:05 +08:00
@geelaw 这个是引用传递,因为 a 和 c 都指向了同一个引用,c 改变了引用的值,a 的值也跟着变了
geelaw
2023-08-19 15:38:03 +08:00
@justonelastdance #5

a 的值没有变,在 b 退出之前 c 的值是 null ,但 b 退出之后 a 不是 null 。

另外“a 和 c 都指向同一个引用”是错误的。a 和 c 代表了不同的存储位置,并且进入 b 的时候 a 和 c 所代表的存储位置具有相同的值,这两个相同的值都是对象引用。
justonelastdance
2023-08-19 16:01:16 +08:00
@geelaw a 的值如果不变的话打印出的应该是{},实际打印出的是{d: 1},因为引用改变了值。后面 c=null 是把 c 指向了另一个引用所以不会造成 a 也是 null
geelaw
2023-08-19 17:01:54 +08:00
另外,Python 也只有传值,最早的 FORTRAN 只有传引用。

@justonelastdance #7 您需要复习 JavaScript 基础知识,a 的值是指向那个对象实例的引用,而不是那个对象实例。在 b 的调用中,通过 c (也是指向那个对象的引用)改变了对象实例,当然可以通过 a 看见。

你当然理解这里发生了什么,但是你的术语用法和计算机科学中的主流用法不符。我暂时找不到教科书,而且我上面的说明已经很明确了,你也可以参考 https://stackoverflow.com/a/7744623/4598348
Ericcccccccc
2023-08-19 17:19:09 +08:00
都是值传递, 你以为的引用传递是传递了地址值.
leonshaw
2023-08-19 17:54:19 +08:00
大部分都是传值,印象里也就 C++, rust 这种有引用传递。简单的区分方法是看函数里 param = xxxx 和函数外 arg = xxxx 是不是同样的效果。
lance6716
2023-08-19 18:04:08 +08:00
@justonelastdance 可以理解为,“引用”指的是 a 这个 name 和 c 这个 name 是同一个东西,对 c “本身”的改变会影响到 a 。而不是他们是两个东西但是具有相同的值且值是一个指针,并通过 .d 影响了同一对象
Rache1
2023-08-19 18:16:37 +08:00
在看到楼上的回复之前,我都以为在 JavaScript 这种,传一个对象进去,然后再方法内部可以改变对象本身成员的值的情况,对于对象就是按引用传递的,而对于标量这种则是按值传递,函数内部对其的赋值不能改变其外部。我想楼主之前也是这样想的。🫥

刚刚去查了一下相关资料,没想到 “传递对象,函数内部改变对象成员值” 的情况也叫按值传递。而按引用传递的就是说在函数内可以直接改变源数据。

受教 💕
agagega
2023-08-19 19:34:14 +08:00
C/C++传参的模型看起来难,但是最灵活和最能帮助理解的
netabare
2023-08-20 03:15:55 +08:00
call by name/call by value 算不算特殊的传参方式?(虽然其实应该是运算策略来着。。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/966646

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX