iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >按值传递 vs. 按指针传递
  • 912
分享到

按值传递 vs. 按指针传递

指针 2023-01-30 22:01:18 912人浏览 薄情痞子

Python 官方文档:入门教程 => 点击学习

摘要

变量赋值有两种方式:按值传递、按"指针"传递(指针也常称为"引用")。不同的编程语言赋值的方式不一样,例如python是按"指针"传递的,Go是按值传递的。 注意,"指针"加了引号,因为它不是真正的按指针拷贝,见下文分析。 参数传值其实

变量赋值有两种方式:按值传递、按"指针"传递(指针也常称为"引用")。不同的编程语言赋值的方式不一样,例如python是按"指针"传递的,Go是按值传递的。

注意,"指针"加了引号,因为它不是真正的按指针拷贝,见下文分析。

参数传值其实也是变量赋值的过程,只不过参数是函数的本地变量而已。

按值传递的意思是每次赋值都拷贝内存中完整的数据结构对象,这时在内存中会保存两份内容完全相同,但地址不同的数据对象。

按"指针"传递的意思是每次赋值都只拷贝内存中数据结构对象的地址,这个地址占用一个机器字长(一个机器字长,在32位cpu上为32bit共4字节,64位则64bit共8字节),当然有些数据结构除了指针还包括其它属性,这时可能会占用数个机器字长。总之,按"指针"传递时,由于只拷贝一份能表示数据对象的属性(比如地址),拷贝的内容非常少,速度非常快。但必须注意,拷贝"指针"后,内存中只有一份数据对象,但将有两份完全相同的指向内存中数据对象的"指针",无论是通过哪个"指针"去修改数据对象,都会影响另一个。

对于那些不支持操作指针的语言,通常会将按"指针"传递称为"浅拷贝(shallow copy)",然后额外提供一个函数或工具实现按指传递,这称为"深拷贝(deep copy)"。

例如:

a=10
b=a

首先会在内存中划分一个格子用来创建数据对象10,然后将这个数据对象的地址保存到变量a中。

如果是按值拷贝的语言,则会在内存中拷贝一份数据对象10的副本,再将这个副本数据对象的地址保存到b中。

显然,a和b保存的地址是不一样的,内存中也有两份内容完全相同的数据对象10。所以,修改a的值时不会影响b的值,修改b的值时不会影响a。

如果是按"指针"拷贝的语言,则会直接拷贝a中的地址并保存到b中。

因为a和b的地址都一样,所以,修改a的值会影响b,修改b的值会影响a。

也许你已经发现了,按"指针"传递时,虽然a、b保存的地址相同,但如果a=11,a将指向新的数据对象,而b仍然指向10,即b=10,修改a并没有影响b。这是因为数值是不可变的,无法在原始的内存地址处修改,也就是无法将10替换成11,所以只要想修改这种不可变的对象就一定会创建新数据对象。对此,有两方面需要说明。

一方面,有些数据对象是可以在原始内存地址处直接进行替换修改的(例如Python中的列表)。假设,某编程语言对数值也是可原处修改的,那么a=11将会在内存中将10替换成11,而不会新创建另一个数据对象11。

另一方面,上面的"按指针传递"并非是真正的按指针传递,而是按引用传递,或者说是按地址传递。这就是前文"按指针传递"中的"指针"都加上了引号的原因。

真正的指针是额外保存的,是占用空间的,和变量不同(变量保存了地址,在栈空间中),它是保存在堆内存中的。对于支持指针操作的语言(如C、c++、Go等),需要使用语法独立生成数据对象的指针,这类语言一般都能直接在原处修改数据对象。例如:

a=10
b=&a

其中b=&a表示生成a所指向(因为a保存了地址)数据对象的一个额外的指针,这个指针中保存了数据对象的地址,然后将这个指针赋值给b,这时b保存的是指针的地址,而不是数据对象的地址。

这时,修改a,或者修改b都会影响另一方,因为支持指针操作的语言一般都支持原处修改:

a=11
print(*b)  

其中*b表示解除指针的引用,也就是取得数据对象的内容。

再回到按"指针"传递的拷贝方式,虽然它不是真正的拷贝指针,而是拷贝地址,但对于那些支持原处修改的数据对象,它们达到的效果和真实的指针传递是一样的。例如,数组、python的列表。

# 以下为python代码:
L1=[1,2,3,4]
L2=L1
L2[0]=11
print(L1)   # 输出:[11,2,3,4]

支持指针操作的语言,通过指针修改数据时,是直接在原始地址块上修改为新数据的。例如:

func main() {
    a := 10
    println(a)
    println(&a)
    println("---------------")
    *(&a) = 20
    println(a)
    println(&a)
}

结果:

10
0xc042085f48
---------------
20
0xc042085f48

但是python中的可变对象(比如列表),虽然俗称"原处修改",但并非真的原处修改,而是在堆内存中新创建一个数据对象,并将它作为可变对象的一部分,所以可变对象整体的地址没有改变,但内部元素的地址已经改变了,也就是旧的元素对象被回收。

>>> L=[222,333,444,555]
>>> id(L),id(L[1])
(44652184, 43798256)
>>> L[1]=3333
>>> id(L),id(L[1])
(44652184, 43798240)

--结束END--

本文标题: 按值传递 vs. 按指针传递

本文链接: https://www.lsjlt.com/news/180186.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 按值传递 vs. 按指针传递
    变量赋值有两种方式:按值传递、按"指针"传递(指针也常称为"引用")。不同的编程语言赋值的方式不一样,例如Python是按"指针"传递的,Go是按值传递的。 注意,"指针"加了引号,因为它不是真正的按指针拷贝,见下文分析。 参数传值其实...
    99+
    2023-01-30
    指针
  • C++之值传递&指针传递&引用传递的示例详解
    目录1.函数基础2.值传递3.指针传递4.引用传递1.函数基础 一个函数由以下四部分组成: 返回类型函数名参数(0个或多个)函数体 其中,函数的参数叫做形参,函数执行的操作的语句块叫...
    99+
    2022-11-13
    C++值传递 指针传递 引用传递 C++ 值传递 C++ 指针传递 C++ 引用传递
  • 如何实现JavaScript的共享传递和按值传递
    这期内容当中小编将会给大家带来有关如何实现JavaScript的共享传递和按值传递,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。关于JavaScript如何将值传递给函数...
    99+
    2022-10-19
  • php按值传递和引用传递的区别是什么
    这篇文章主要讲解了“php按值传递和引用传递的区别是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“php按值传递和引用传递的区别是什么”吧!说明按值传递中php必须复制值。特别是对于大型...
    99+
    2023-06-20
  • C#怎么实现按值传递参数
    这篇文章主要讲解了“C#怎么实现按值传递参数”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C#怎么实现按值传递参数”吧!按值传递参数这是参数传递的默认方式。在这种方式下,当调用一个方法时,会...
    99+
    2023-06-17
  • php函数是如何按值传递参数的
    本篇内容主要讲解“php函数是如何按值传递参数的”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“php函数是如何按值传递参数的”吧!向函数传递参数的方式有四种,分别是值传递、引用传递、默认参数和可...
    99+
    2023-06-20
  • JavaScript中参数按值传递的示例分析
    小编给大家分享一下JavaScript中参数按值传递的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!定义ECMAScri...
    99+
    2022-10-19
  • php函数按值传递参数的实例方法
    本篇内容主要讲解“php函数按值传递参数的实例方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“php函数按值传递参数的实例方法”吧!向函数传递参数的方式有四种,分别是值传递、引用传递、默认参数...
    99+
    2023-06-20
  • C++ 指针传递的作用小结
    本文主要介绍了C++ 指针传递的作用小结,分享给大家,具体如下 void pointerTest(int num) { num = 20; } int main() { ...
    99+
    2023-05-15
    C++ 指针传递 C++ 传递指针
  • vbscript能不能按引用传递参数
    本篇内容主要讲解“vbscript能不能按引用传递参数”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“vbscript能不能按引用传递参数”吧!vbscript 可以按引用传递参数吗? ...
    99+
    2023-06-09
  • Java应用程序中的按值传递语义是什么
    这篇文章给大家介绍Java应用程序中的按值传递语义是什么,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。Java 应用程序中的按值传递语义 节选理解参数是按值而不是按引用传递的说明 Java 应用程序有且仅有的...
    99+
    2023-06-03
  • php值传递指的是什么
    这篇文章主要介绍了php值传递指的是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇php值传递指的是什么文章都会有所收获,下面我们一起来看看吧。在php中,值传递是指在调用函数时将实际参数复制一份再传递给函...
    99+
    2023-07-05
  • C++指针传递的作用是什么
    这篇文章主要介绍了C++指针传递的作用是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C++指针传递的作用是什么文章都会有所收获,下面我们一起来看看吧。具体如下void pointerTest(i...
    99+
    2023-07-05
  • C#怎么实现按输出传递参数
    这篇文章主要讲解了“C#怎么实现按输出传递参数”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C#怎么实现按输出传递参数”吧!按输出传递参数return 语句可用于只从函数中返回一个值。但是,...
    99+
    2023-06-17
  • C#怎么实现按引用传递参数
    今天小编给大家分享一下C#怎么实现按引用传递参数的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。按引用传递参数引用参数是一个对...
    99+
    2023-06-17
  • vue怎么通过按钮传递新页面
    在Vue中,我们可以通过路由来实现页面之间的跳转。在本文中,我们将探讨如何在Vue中使用按钮传递到新页面。我们将使用Vue的官方路由器插件Vue Router。Vue Router是Vue.js官方路由器。它允许我们设置路由表,将一些URL...
    99+
    2023-05-23
  • VB.NET窗体指针如何在项目中传递
    这篇文章给大家分享的是有关VB.NET窗体指针如何在项目中传递的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。VB.NET窗体指针在项目中的传递除了把窗体实例全局化以外,你还可以把VB.NET窗体指针保存在变量中传...
    99+
    2023-06-17
  • c语言怎么向函数传递数组指针
    在C语言中,可以通过指针的方式向函数传递数组指针。以下是一个示例代码: #include void printArray(int...
    99+
    2023-10-25
    c语言
  • Qt中简单的按钮槽函数传递参数方法
    目录Qt按钮槽函数传递参数方法Qt槽函数的几种用法通过ui控件添加槽函数通过connect连接Qt按钮槽函数传递参数方法 Qt中一个典型的点击按钮触发槽函数的写法是: connect...
    99+
    2022-11-13
    Qt按钮槽函数 按钮槽传递参数 Qt按钮槽传递参数
  • C语言汇编分析传递结构体指针比传递结构体变量高效的深层原因
    目录前言传递结构体变量传递结构体指针总结前言 先声明下观点:当有少量结构体成员时,传递结构体指针和结构体变量的差距不大;当有大量结构体成员时,随着成员越来越多,传递指针的效率也越来越...
    99+
    2022-11-13
    C语言汇编分析 C语言传递结构体指针 C语言传递结构体变量
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作