gm怎么刷东西 rust_Rust语言:解引用详述,搞不明白这个概念,趁早放弃Rust
Rust是內(nèi)存安全的,對新手來說,最大的困難是可惡的編譯器,在其他語言上面叱咤風(fēng)云,偏偏被Rust搞到崩潰。所以,大家都戲謔道,Rust是面向編譯器編程。
和編譯器做斗爭的過程中,遇到最多的是,變量所有權(quán)被move了,某個(gè)api需要傳入可變引用而我卻不知道如何獲取。
只要你了解了如何解引用,如何做類型轉(zhuǎn)換,這些問題都將迎刃而解。
什么是解引用
引用是對內(nèi)存塊的借用,Rust里每一個(gè)內(nèi)存塊都是有主人的,主人就是對內(nèi)存擁有所有權(quán)的變量,沒有主人的內(nèi)存塊我們稱之為內(nèi)存泄露了。
解引用是通過引用找到內(nèi)存塊真正的主人,然后你可以跟主人借一些不同類型的引用,比如從&mut T借成Pin<&mut T>。
這個(gè)主人可能被包了很多層,當(dāng)你以為你找了主人,其實(shí)它只是個(gè)皮,所以會(huì)存在不斷解引用的情況,你可能需要加很多個(gè)*,當(dāng)然很多個(gè)*不符合設(shè)計(jì)美感。
Rust語法規(guī)定,同一塊內(nèi)存只能有一個(gè)可變引用,或者有多個(gè)不可變引用。這給習(xí)慣于C++或者Java等語言的編程人員造成了很大的困擾,違反了多年以來養(yǎng)成的編程習(xí)慣,特別的別扭,因?yàn)樗麄冄壑性镜睦斫馐撬械囊枚际强勺円谩?/p>
Rust之所以這么規(guī)定,一個(gè)非常大的優(yōu)點(diǎn)是避免了內(nèi)存被多處修改的潛在隱患,避免了資源的復(fù)雜環(huán)境競爭,降低了程序的調(diào)試難度。
那么,程序編寫過程中必然會(huì)在不同的函數(shù)塊里調(diào)用同一塊內(nèi)存,所以引用的使用將會(huì)變得非常頻繁,我們犯的錯(cuò)誤大多也在此。
解引用的方法
解引用可以分為,自動(dòng)解引用和手動(dòng)解引用。
Rust為了減少某些場合下重復(fù)解引用導(dǎo)致的代碼美觀問題,在編譯期做了一些智能識(shí)別功能,比如帶有&T參數(shù)的函數(shù)被調(diào)用的時(shí)候,你傳&&&......&&&T都可以自動(dòng)解引用,直到符合函數(shù)的參數(shù)類型為止。
手動(dòng)解引用,就是和其他語言類似,借用是&操作符,解引用是*操作符。
我們也可以通過自行實(shí)現(xiàn)Deref這個(gè)Trait來自定義解引用的最終目標(biāo)是什么,而恰恰這個(gè)也是Rust語言最難的地方,你得了解每個(gè)類型是否實(shí)現(xiàn)了Deref,而Rust類型實(shí)在是太多了,連&T借用也算一個(gè)新的類型,&T是不能繼承T的所有特性的。
如果想要學(xué)好Rust,對Deref不做深入的研究,將會(huì)死的很難看。
解引用進(jìn)階篇
1、手動(dòng)實(shí)現(xiàn)Deref
Rust已經(jīng)為所有的&T和&mut T的類型默認(rèn)實(shí)現(xiàn)了簡陋版的Deref,解引用就是得到T本身。
當(dāng)然我們也可以給類型T本身添加一個(gè)Deref,這樣T本身就可以被接引用,相當(dāng)于T也是一個(gè)引用類型,其實(shí)T不是。
下面這個(gè)短暫的動(dòng)態(tài)圖片形象的闡述了Deref是如何自定義的,以及遇到類型不匹配的函數(shù)時(shí),Rust是會(huì)自動(dòng)解引用直到類型匹配為止。
2、以Pin<P>為例子,來談?wù)劷庖?/p>
如果P沒有實(shí)現(xiàn)Deref,即P不可以解引用,那么Pin<P>是不能被*操作符操作的。
當(dāng)P實(shí)現(xiàn)了Deref,那么*Pin<P>的解引用會(huì)先觸發(fā)P解引用操作,得到P的Target的引用,再使用*操作符,最終的結(jié)果是P的Target被返回了。然而Pin<P>本身使用deref()得到的是&Target。
所有實(shí)現(xiàn)Deref的類型,使用deref函數(shù)得到的結(jié)果,肯定是一個(gè)引用類型。
*操作符為了更通用和方便,原理就是將被解引用的對象,先使用deref調(diào)用一下,再解引用。
項(xiàng)目中,最常遇見的是Pin<&mut T>,我們希望得到T的Target的可變引用,一般使用&mut **Pin<&mut T>。如果不了解它是怎么執(zhí)行的,那么肯定會(huì)很疑惑,這個(gè)結(jié)果是啥。
3、Option<T>如何得到T的Target引用
大多數(shù)情況下,我們得到的是Option<T>,可是我們想調(diào)用的函數(shù)需要傳入&T或者T的Target引用,這樣就會(huì)很疑惑,該怎么得到這個(gè)&T呢?
這里也涉及到幾個(gè)類型的deref函數(shù)的調(diào)用,首先是要把Option<T>轉(zhuǎn)化為Option<&T>,然后再將T轉(zhuǎn)化為Target引用,如Option.as_ref().map(|s| { s.deref()}),或者直接使用Option自帶的as_deref()。
4、Box<T>是個(gè)特例
嚴(yán)格說Box這個(gè)語法在Rust里是特權(quán)一般的存在,各種小后門開的不亦樂乎。
Box<T>在實(shí)現(xiàn)Deref這個(gè)Trait時(shí),竟然使用的是&**語法,可是*操作符必須作用在實(shí)現(xiàn)Deref的類型上,這到底是先有的雞,還是先有的蛋呢?
所以,不需要糾結(jié)這種被Rust開洞的特例,會(huì)使用即可。
寫在最后
*操作符的特性是,先將作用對象進(jìn)行deref得到一個(gè)引用,再將&引用清除。如果只是想得到一個(gè)引用,那么使用&*或者deref()。
如果不好理解,可以這么去記憶:*是用來消除&和box符號(hào)的,當(dāng)發(fā)現(xiàn)目標(biāo)沒有&和box,就會(huì)調(diào)用deref函數(shù)去生成帶有&符號(hào)的類型,然后就可以愉快的消除了。
掌握好這個(gè)技巧,在遇到各種&和*操作符的時(shí)候,才不至于被迷惑,找不到深層次的代碼的實(shí)現(xiàn)原理。
如果你對技術(shù)也有追求,對現(xiàn)實(shí)迷茫,請關(guān)注我,帶你一起學(xué)習(xí)成長。總結(jié)
以上是生活随笔為你收集整理的gm怎么刷东西 rust_Rust语言:解引用详述,搞不明白这个概念,趁早放弃Rust的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何取消 登录_LSAT | 退考、缺考
- 下一篇: ad如何镜像器件_使用 Dockerfi