亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定

按值傳遞 vs. 按指針傳遞

標簽:
Python

按值传递还是指针传递?

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

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

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

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

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

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

例如:

a=10b=a

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

5be859e00001433202750103.jpg

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

5be859e100018b7d02770171.jpg

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

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

5be859e10001e38803090165.jpg

因为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。

5be859e20001a03203540172.jpg

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

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

a=10b=&a

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

5be859e20001be2502660211.jpg

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

a=11print(*b)  /* 输出11 */

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

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

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

5be859e20001a9f604120173.jpg

 

转载请注明出处:https://www.cnblogs.com/f-ck-need-u/p/9928418.html


點擊查看更多內容
TA 點贊

若覺得本文不錯,就分享一下吧!

評論

作者其他優質文章

正在加載中
  • 推薦
  • 評論
  • 收藏
  • 共同學習,寫下你的評論
感謝您的支持,我會繼續努力的~
掃碼打賞,你說多少就多少
贊賞金額會直接到老師賬戶
支付方式
打開微信掃一掃,即可進行掃碼打賞哦
今天注冊有機會得

100積分直接送

付費專欄免費學

大額優惠券免費領

立即參與 放棄機會
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號

舉報

0/150
提交
取消