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

简介: 最近一年多的时间陆续接触了一些对我来说陌生的语言,主要就是 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月更文挑战第30天】研究人员发现,在有限计算资源下,优化大型语言模型的训练需使模型大小和训练数据量成比例增长,以达到计算最优。通过训练700亿参数的Chinchilla模型并对比GPT-3等,验证了该策略的有效性。论文强调数据集质量和伦理隐私问题,并提出预测模型扩展的方法。这一发现对AI领域的模型训练策略提供了新思路,但也面临数据质量和伦理挑战。
183 2
论文介绍:训练计算最优的大型语言模型
|
10月前
|
搜索推荐 Python
使用Python自动化生成物业通知单
本文介绍如何使用Python结合Pandas和python-docx库自动化生成物业通知单。通过读取Excel数据并填充至Word模板,实现高效准确的通知单批量制作。包括环境准备、代码解析及效果展示,适用于物业管理场景。
235 14
|
5月前
|
人工智能 搜索推荐 前端开发
从代码到心灵对话:我的CodeBuddy升级体验之旅(个性化推荐微服务系统)
本文分享了使用CodeBuddy最新版本的深度体验,重点探讨了Craft智能体、MCP协议和DeepSeek V3三大功能。Craft实现从对话到代码的无缝转化,大幅提升开发效率;MCP协议打通全流程开发,促进团队协作;DeepSeek V3则将代码补全提升至新境界,显著减少Bug并优化跨语言开发。这些功能共同塑造了AI与程序员共生的未来模式,让编程更高效、自然。
561 15
|
SQL 数据采集 安全
Burpsuite测试神器使用
Burpsuite测试神器使用
|
10月前
|
C语言
【C语言】逗号运算符详解 - 《不起眼的 “逗号”》
逗号运算符(`,`)是C语言中的一个二元运算符,它会对两个操作数进行求值,并返回最后一个操作数的值。其主要作用是将多个表达式组合成一个复合表达式。
470 7
|
缓存 网络协议 前端开发
dns-prefetch DNS 预解析
dns-prefetch DNS 预解析
|
存储 数据库 开发者
Django Web架构:全面掌握Django模型字段(下)
Django Web架构:全面掌握Django模型字段(下)
195 2
|
存储 JavaScript 前端开发
JavaScript基础-字符串操作方法
【6月更文挑战第11天】本文介绍了JavaScript中字符串的基本操作,包括创建与访问、查找与替换、大小写转换等,并强调了字符串的不可变性。通过实例代码展示了如何避免常见错误,如混淆查找与替换方法、正则表达式使用不当。学习这些技巧能提升代码健壮性和效率。
119 3
|
存储 云计算
阿里云产品体系分为6大分类——云计算基础——存储服务——智能存储
阿里云产品体系分为6大分类——云计算基础——存储服务——智能存储自制脑图
690 1
阿里云产品体系分为6大分类——云计算基础——存储服务——智能存储
|
存储 运维 监控
centos7.6部署Postfix+Dovecot邮件系统
一、理论部分 电子邮件系统基于邮件协议来完成电子邮件的传输 常用的协议有:    简单邮件传输协议(SMTP):用于发送和中转发出的电子邮件,占用服务器的TCP/25端口    邮局协议版本3(POP3):用于将电子邮件存储到本地主机,占用服务器的TCP/110端口    internet消息访问协议版本4(IMAP4):用于在本地主机访问邮件,占用服务器的TCP/143端
626 0
centos7.6部署Postfix+Dovecot邮件系统