c++引用参数例子_Python 到底是传值还是传引用?

1e3be05ee9a6ba8765c5c5928cae2761.png

Python 到底是传值还是传引用?

这个问题我看到过很多解释,一种比较普遍的解释是这样的:

Python 中同时存在传值和传引用,如果参数是基本类型,那么就是传值调用,如果参数是容器类型,那么就是传引用调用。

如果有 C++ 编程经验就会发现,这可能并不是事实。

函数如何调用

首先,我们需要搞清楚函数调用中参数是如何传递的,这是函数传值或者传引用最根本的区别。

在《深入 Python》系列中我们已知,函数调用会在调用栈中创建新的栈帧(Frame),其中包含了函数中所需要的所有局部变量,Python 的参数也被包含在函数自身的 local 字典中:

def test(a, b):
    c = 5  
    # 打印所有局部变量
    print(locals())
    return (a + b) * c
x = 1
y = 2
test(x, y)
# 输出
# {'a': 1, 'b': 2, 'c': 5} 

所以在 Python 的调用中,发生了 x->a, y->b 的赋值操作,所以在 test 函数中的 a,b 是 x,y 的副本,只不过是他们的值相同,所以被称为传值调用。

如果是传引用调用,那么在函数中应当可以直接访问外部参数,而非栈帧中的副本。

反例

很多说 Python 函数调用也可能是传引用,一个例子是函数的参数是容器的时候,可以通过参数改变容器内容。

其实以此说明传入的容器是传引用调用是不合适的。如果函数是传引用调用,那么我们应当可以在函数内直接交换参数。

def swap(a, b):
    tmp = a
    a = b
    b = tmp

x = [1,2,3]
y = ['a', 'b', 'c']

swap(x, y)


# 输出 x 
# [1, 2, 3]
# 输出 y
# ['a', 'b', 'c']
# 没有变化 

但实际上并不能。所以当参数是容器的时候,函数也是传值调用,只不过这个值正好是个容器的引用而已。

更严格的说,Python 中所有变量都是 “引用”,它的行为更接近 C 语言中的指针。

C++ 中的传值和传引用

C++ 同时支持两种传值方式,下面是一段 demo:

#include <iostream>

// 传入指针变量的 引用
void swap(int * &a, int * &b){
    int * tmp = a;
    a = b;
    b = tmp;
}

// 传入指针变量
void bad_swap(int * a, int * b){
    int * tmp = a;
    a = b;
    b = tmp;
}


int main(){
    int a[] = {1,2,3};
    int b[] = {5,4,3};

    int * ap = a;
    int * bp = b;

    std::cout<< ap[0] << std::endl;   // 输出 1
    swap(ap, bp);                     // 传引用调用,函数直接改变了两个参数
    std::cout<< ap[0] << std::endl;   // 输出 5
    bad_swap(ap, bp);                 // 传值调用,改变的只是函数栈中的局部变量,无效
    std::cout<< ap[0] << std::endl;   // 无变化,依然输出 5

    return 1;
} 

注意 swap(ap, bp);bad_swap(ap, bp); 两个函数的调用参数完全一样,但只有传引用调用才可以影响实参。

而 Python 的函数调用相当于 bad_swap,确实是传值调用。

首发公众号 “江川Go”,关注了解程序员的烧脑日常。

42f060c8b085e6e67fec5d77be062e0f.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值