一文搞懂参数传递原理(下)

简介: 最近一年多的时间陆续接触了一些对我来说陌生的语言,主要就是 Python 和 Go,期间为了快速实现需求只是依葫芦画瓢的撸代码;并没有深究一些细节与原理。 就拿参数传递一事来说各个语言的实现细节各不相同,但又有类似之处;在许多新手入门时容易搞不清楚,导致犯一些低级错误。

使用建议


那我们在什么时候使用指针呢?有以下几点建议:


  • 如果参数是基本的值类型,比如 int,float 建议直接传值。


  • 如果需要修改基本的值类型,那只能是指针;但考虑到代码可读性还是建议将修改后的值返回用于重新赋值。


  • 数据量较大时建议使用指针,减少不必要的值拷贝。(具体多大可以自行判断)


Python


Python 中变量是否可变是影响参数传递的重要因素:


网络异常,图片无法展示
|


如上图所示,bool int float 这些不可变类型在参数传递过程中是不能修改原始数据的。


if __name__ == '__main__':
    x = 1
    modify(x)
    print('最终 x={}'.format(x))  
def modify(val):
    val = 2
最终 x=1


原理与 Java Go中类似,是基于值传递的,这里就不再复述。


这里重点看看可变数据类型在参数传递中的过程:


if __name__ == '__main__':
    x = [1]
    modify(x)
    print('最终 x={}'.format(x))  
def modify(val):
    val.append(2)
最终 x=[1, 2]


最终数据受到了影响,那么就表明这是引用传递嘛?再看个例子试试:


if __name__ == '__main__':
    x = [1]
    modify(x)
    print('最终 x={}'.format(x))  
def modify(val):
    val = [1, 2, 3]
最终 x=[1]


显而易见这并不是引用传递,如果是引用传递最终 x 应当等于 [1, 2 ,3]


从结果来看这个传递过程非常类似 Go 中的指针传递,val 拿到的也是 x 这个参数内存地址的拷贝;他们都指向了同一块内存地址。


所以对这块数据的修改本质上改的是同一份数据,但一旦重新赋值就会创建一块新的内存从而不会影响到原始数据。


网络异常,图片无法展示
|


Java 中的上图类似。


所以总结下:


  • 对于不可变数据:在参数传递时传递的是值,对参数的修改不会影响到原有数据。


  • 对于可变数据:传递的是内存地址的拷贝,对参数的操作会影响到原始数据。


这么说来这三种都是值传递了,那有没有引用传递的语言呢?


当然,C++是支持引用传递的:


#include <iostream>
using namespace std;
class Box
{
   public:
      double len;
};
void modify(Box& b);
int main ()
{
  Box b1;
  b1.len=100;
  cout << "调用前,b1 的值:" << b1.len << endl;
  modify(b1);
  cout << "调用后,b1 的值:" << b1.len << endl;
  return 0;
}
void modify(Box& b)
{
  b.len=10.0;
  Box b2;
  b2.len = 999;
  b = b2;
  return;
}
调用前,b1 的值:100
调用后,b1 的值:999


可以看到把新对象 b2 赋值给入参 b 后是会影响到原有数据的。


总结


其实这几种语言看下来会发现他们中也有许多相似之处,所以通常我们在掌握一门语言后也能快速学习其他语言。


但往往是这些基础中的基础最让人忽略,希望大家在日常编码时能够考虑到这些基础知识多想想一定会写出更漂亮的代码(bug)。


相关文章
|
2月前
|
算法 编译器 C++
【C++ 函数 基本教程 第二篇 】深度剖析C++:作用域与函数查找机制
【C++ 函数 基本教程 第二篇 】深度剖析C++:作用域与函数查找机制
34 0
|
8月前
|
自然语言处理 前端开发 JavaScript
前端经典面试题 | 闭包的作用和原理
前端经典面试题 | 闭包的作用和原理
|
4月前
|
SQL 关系型数据库 MySQL
搞懂connectTimeout和socketTimeout的区别
搞懂connectTimeout和socketTimeout的区别
76 0
|
4月前
|
存储 缓存 自然语言处理
【面试题】深入理解闭包的形成过程及应用!
【面试题】深入理解闭包的形成过程及应用!
|
11月前
|
存储 编译器 C语言
【C】函数真的难嘛?其实一点也不难,原理很简单。
# 什么是函数 程序是由多个零件组合而成的,而函数就是这种“零件”的一个较小单位。 ## main函数和库函数 C语言程序中,main函数是必不可少的。程序运行的时候,会执行main函数的主题部分。main函数中使用了printf、scanf、puts等函数。由C语言提供的这些为数众多的函数称为库函数。 ## 什么是函数 当然,我们也可以自己创建函数。而实际上,我们也必须亲自动手创建各种函数。下面我们来自己创建一个简单的函数。 创建一个函数,接收两个整数参数,返回较大整数的值。 printf函数和scanf函数等创建得比较好得函数,即使不知道其内容,只要了解使用方法,也可以轻松使用。 ## 函
|
11月前
|
C语言
一直没有搞懂的C语言参数传递,今天终于明白了
一直没有搞懂的C语言参数传递,今天终于明白了
71 0
|
12月前
手写函数柯里化原理
手写函数柯里化原理记录
41 1
setlocale函数是干什么的?底层原理是什么?
setlocale函数是干什么的?底层原理是什么?
382 0
|
自然语言处理
闭包的原理跟作用
闭包的原理跟作用
116 0
|
Java Go Python
一文搞懂参数传递原理(中)
最近一年多的时间陆续接触了一些对我来说陌生的语言,主要就是 Python 和 Go,期间为了快速实现需求只是依葫芦画瓢的撸代码;并没有深究一些细节与原理。 就拿参数传递一事来说各个语言的实现细节各不相同,但又有类似之处;在许多新手入门时容易搞不清楚,导致犯一些低级错误。