多种(C++、Java、JavaScript、Python)编程语言参数传递方式介绍(修订)

多种(C++、Java、JavaScript、Python)编程语言参数传递方式介绍(修订)

参数传递方式指的是实际参数(实参)和形式参数(形参)在传递过程中是如何对应和实现的。不同编程语言在处理参数传递时有区别,了解掌握参数传递方式有助于理解函数对形参的修改是否会影响实参。

在编程语言中,参数(parameter)是用于向函数、方法或过程传递数据的一种机制。在编程语言中,参数(parameter,也称为形式参数)是一种特殊类型的变量,用于在函数或方法的定义中表示将要接收的信息。当函数被调用时,实参(也称为实际参数,argument)被传递给形式参数。这些值可以用于函数内部的计算,并可以影响函数的行为。参数的传递方式确实取决于编程语言的规范,而且不同的传递方式会对函数的行为产生不同的影响。理解和掌握这些参数传递方式的关键在于理解它们的工作原理和适用场景。你可以通过阅读编程教程和参考书籍,以及编写和测试代码来学习和实践。同时,理解不同编程语言的特性和设计理念也有助于你理解参数传递方式的差异和用途。

本文介绍C++、Java、JavaScript、Python语言的参数传递方式。

★C++中的情况

☆参数的传递方式有三种:传值、传引用和传指针。

按值传递(Pass by Value):这是C++函数参数的默认传递方式。在这种情况下,函数接收的是参数值的一个副本,而不是参数本身——实参的值会被复制到形参中。因此,函数内对参数的任何修改都不会影响原始参数。

按引用传递(Pass by Reference):在C++中,可以通过引用来传递参数。这种情况下,函数接收的是参数的引用,而不是值的副本。这意味着函数内对参数的任何修改都会影响到原始参数。在C语言中,没有按引用传递,但可以通过指针实现类似的效果。

按指针传递(Pass by Pointer): C++中,可以通过指针来传递参数。在这种情况下,函数接收的是指向参数的指针。函数内可以通过该指针修改原始参数的值。

#include <iostream>
using namespace std;
 
void passByValue(int num) {
    num = 10;  // 修改形参的值
}
 
void passByReference(int& num) {
    num = 10;  // 修改原始参数的值
}
 
int main() {
    int num1 = 5;
    int num2 = 5;
 
    passByValue(num1);
    cout << "After passByValue, num1 = " << num1 << endl;  // 输出 5
 
    passByReference(num2);
    cout << "After passByReference, num2 = " << num2 << endl;  // 输出 10
 
    return 0;
}

可参见 C++函数 https://blog.csdn.net/cnds123/article/details/108917528 一文有关部分
C++向函数传递参数的三种方式:传值、指针、引用 https://zhuanlan.zhihu.com/p/163290371

★Java情况

☆参数传递按值传递。

传递基本数据类型(Primitive Data Type)参数,基本参数,如int型或double型,按值传递给方法。传递引用数据类型( Reference Data Type)参数,引用数据类型参数(如对象)也按值传递给方法。【Oracle官方文档中对于Java参数传递方式的介绍 https://docs.oracle.com/javase/tutorial/java/javaOO/arguments.html

Java 中的参数传递方式只有按值传递。无论是基本数据类型还是引用类型,都是按值传递。 1)对于基本数据类型(如整数、浮点数、布尔值等),函数接收的是该值的副本,方法(函数)内部对副本的修改不会影响到原始的值。 2)对于引用类型(如对象、数组等),函数接收的是对象引用的副本,也就是地址的副本。这意味着方法(函数)内部对引用的修改会影响到原始的对象。

可参见  Java面向对象(上)https://blog.csdn.net/cnds123/article/details/110915227 一文有关部分

Java中的所有参数都通过值传递。在Java中所有的参数传递,不管基本类型还是引用类型,都是值传递,或者说是副本传递。
在传递过程中:
如果是对基本数据类型的数据进行操作,由于原始内容和副本都是存储实际值,并且是在不同的栈区,因此形参的操作,不影响原始内容。
如果是对引用类型的数据进行操作,分两种情况,
一种是形参和实参保持指向同一个对象地址,则形参的操作,会影响实参指向的对象的内容。
一种是形参被改动指向新的对象地址(如重新赋值引用),则形参的操作,不会影响实参指向的对象的内容。https://zhuanlan.zhihu.com/p/89794950

深入理解Java中方法的参数传递机制 https://www.cnblogs.com/sum-41/p/10799555.html
Java的参数传递是「按值传递」还是「按引用传递」?https://zhuanlan.zhihu.com/p/90197085

★JavaScript(JS)情况

☆参数传递按值传递。

参数传递方面,在 JavaScript中,参数传递方式是按值传递——传递的是副本。具体说来:1)当将一个值类型(如数字、字符串、布尔值等)作为参数传递给函数时,实际上是将该值的一个副本传递给函数——将实参值复制给形参,实参和形参相互独立互不干扰。函数内部对该副本的修改不会影响到原始的值。2)当将一个引用类型(如对象、数组等)作为参数传递给函数时,传递的是该对象的引用(地址)的副本——将实参引用的地址值复制给形参,形参和实参指向同一个对象的地址,改变形参所指向的对象的属性将影响实参所指向的对象。需要注意,在引用类型的参数传递中,并不会改变形参的值(即引用的地址),而是通过形参改变它所指向的对象的属性。

Arguments are always passed by value and never passed by reference. This means that if a function reassigns a parameter, the value won't change outside the function. More precisely, object arguments are passed by sharing, which means if the object's properties are mutated, the change will impact the outside of the function.
【选自https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions 】
译文:实参总是按值传递,而不是按引用传递。这意味着,如果函数重新赋值一个参数,该值在函数外部不会改变。更准确地说,对象参数是通过共享传递的,这意味着如果对象的属性发生了变化,那么这种变化将影响函数的外部。
解析一下:
JS调用函数时,参数本质上是按值传递给函数的。传递给函数的值被称为函数的实参(值传递),对应位置的函数参数名叫作形参。如果实参是一个包含原始值 (数字,字符串,布尔值) 的变量,则就算函数在内部改变了对应形参的值,返回后,该实参变量的值也不会改变。如果实参是一个对象引用,则对应形参会和该实参指向同一个对象。假如函数在内部改变了对应形参的值,返回后,实参指向的对象的值也会改变。

可参见 JavaScript函数 https://blog.csdn.net/cnds123/article/details/109405136 一文有关部分

JS中的参数传递详解 https://www.zhihu.com/tardis/zm/art/335726112

JavaScript 基础深入——数据、变量、内存https://segmentfault.com/a/1190000019062349

★Python情况

☆python的参数传递机制,正确的叫法应该是按对象引用调用(call by object reference)。调用者和被调用者之间共享这个对象,而对于不可变对象,由于并不能真正被修改,因此,修改往往是通过生成一个新对象然后赋值来实现的。

 下面是官网文档节选【 https://docs.python.org/zh-cn/3/tutorial/controlflow.html#defining-functions

在调用函数时会将实际参数(实参)引入到被调用函数的局部符号表中;因此,实参是使用 按值调用(call by value) 来传递的(其中的 值 始终是对象的引用 而不是对象的值)[1] 。

[备注1]实际上,按对象引用调用(call by object reference) 这种说法更好,因为,传递的是可变对象时,调用者能发现被调者做出的任何更改(插入列表的元素)。

:如何编写带有输出参数的函数(按照引用调用)?【见https://docs.python.org/zh-cn/3/faq/programming.html#how-do-i-write-a-function-with-output-parameters-call-by-reference

请记住,Python 中的实参是通过赋值(assignment)传递的。由于赋值只是创建了对象的引用,所以调用方(caller)和被调用方(callee)的参数名都不存在别名,本质上也就不存在按引用调用(call-by-reference)的方式。通过以下几种方式,可以得到所需的效果。(下面是例子,略)

解析一下,这意味着:如果你尝试在函数内部重新赋值一个新的对象给参数,这个改变不会影响到函数外部的实际参数。因为在Python中,变量名和数据是分开的,变量名只是指向数据的引用,而不是数据本身。然而,你可以通过一些方法达到类似引用传递的效果。例如,你可以传递一个可变对象(如列表或字典),然后在函数内部修改这个对象。由于对象的引用被传递,所以这些修改会反映在函数外部。这就是所谓的“共享传递”(pass by sharing)。

想更多了解,可参见  python函数 https://blog.csdn.net/cnds123/article/details/108179769 一文有关部分

从内存管理的角度看,Python语言的变量和参数传递情况 https://blog.csdn.net/cnds123/article/details/134159800

理解PYTHON的参数传递、变量赋值及可变对象和不可变对象https://qcloud.fun/2020/04/11/python-call-by-object-reference/

Python 函数的参数传递https://zhuanlan.zhihu.com/p/118671408

深刻理解 python中函数的参数 引用的传递方式https://blog.csdn.net/andybegin/article/details/85097459

Python里参数是值传递还是引用传递?https://zhuanlan.zhihu.com/p/362702418

补充:《流畅的Python》(Fluent Python)第2版 P213 “Function Parameters as References”部分,这样说:
The only mode of parameter passing in Python is call by sharing. That is the same mode used in most object-oriented languages, including JavaScript, Ruby, and Java (this applies to Java reference types; primitive types use call by value). Call by sharing means that each formal parameter of the function gets a copy of each reference in the arguments. In other words, the parameters inside the function become aliases of the actual arguments.
翻译:Python中参数传递的唯一方式是“共享调用”(call by sharing)。这也是大多数面向对象语言——包括JavaScript,Ruby和Java(这适用于Java的引用类型;原始类型使用值调用)——所使用的模式。共享调用意味着函数中的每个形式参数都会获得实际参数中每个引用的副本。换句话说,函数内的形参变成了实际参数的别名。

【说明:“共享调用”(Call by Sharing)也称为"按共享传递"(Pass by Sharing)。

编程语言中的参数传递方式主要有以下几种:
☆ 值传递(pass by Value):这是最常见的传递方式。在这种方式中,函数的实际参数将其值复制给函数的形式参数。在这种情况下,修改形式参数的值不会影响实际参数。
☆ 引用传递(pass by Reference):在这种方式中,函数的实际参数和形式参数共享内存空间,因此,修改形式参数的值会影响实际参数。
☆ 按指针传递(Pass by Pointer)也是一种常见的参数传递方式,主要在C和C++等语言中使用。在这种方式中,函数的实际参数将其地址复制给函数的形式参数,形式参数接收的是一个指针。这样,形式参数和实际参数都指向同一块内存地址,修改形式参数的值会影响实际参数。这种方式和按引用传递有些类似,但处理方式和细节有所不同。
☆ 共享传递(pass by Sharing):这是Python和许多其他面向对象语言使用的传递方式。在这种方式中,函数的形式参数获得实际参数的引用的副本。这意味着形式参数和实际参数引用同一个对象,所以如果你修改的是对象,那么这些修改会反映到函数外部。但是,如果你试图重新分配一个新的对象给形式参数,这将不会影响实际参数。
☆ 名称传递(pass by Name):这是一种少见的参数传递方式,主要在一些旧的或者函数式编程语言中使用,如Algol和Haskell。在这种方式中,实际参数的表达式在函数内部被直接替换到形式参数的位置。】

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学习&实践爱好者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值