RUST 引用

let x = 5;指針

let y = &5;內存

let z= &x;編譯器

x 是 i32 整型,y,z 是引用類型,用 & 是取引用符it

新加變量 x, 並綁定 5 數據,編譯

新增長變量 y,並綁定 5 數據的引用地址變量

新增變量 z, 並綁定 x 的引用地址原理

上面每一個變量在內存中都是不一樣的存儲引用

第一行,在棧中添加變量,並且變量的值是 5,都在棧中程序

第二行,在棧中增長一個數據 5,再再棧中建立一個變量 y,並把 5 所在的內存地址,給 y;im

第三行 在棧中增長一個變量,把 x 所在的內存地址賦值給 z

每行都是在內存新開闢一塊空間,存變量,並且變量的值都是不一樣的,y 和 z 的內存地址並不相同

let x = 5;

let h = &x;

let k = &x;

上面 h,k 擁有相同的值,x 的內存地址肯定,h,k 都是取 x 的內存地址,全部 h 和 k 是同等的,根據以前的說明,那若是

let g = &5; 是否是就說明 h==k 是 true, h==g 是 false,k==g 也是 false

其實否則,雖然 g=&5; g 的值和 h,k 都不相同,可是在調用 == 的時候,會產生自動解碼的操做,會直接比較指針的值因此,h==g 和 k==g 都是 true

有點須要特別說明,指針的指針這種狀況,看下面例子, 先不提有沒有必要,編譯器是支持的

let x = 5;

let y = &&x;

let z = &&x;

y 和 z 的內存地址是不相同的,具體的原理不是很明白,就根據個人理解(我讓我信服的理由)&x 取 x 的引用保存到一塊空間,&&x 而後再取這個空間的地址,由於咱們並無把 &x; 存這塊空間綁定到一個變量上,因此每次取 &x, 都會產生一個新的空間,因此每次取這個地址都是一個新的內存地址。

 

最後說下解引用,就是用 * 號來解引用,使用引用指向的數據,若是沒有解引用,那就是

let x = 5;

let y = &5;

let z = x+*y;

上面代碼沒有錯,正常編譯執行,y 的類型是個 引用類型,* 號把 y 解引用就是 5,相加正常,

若是 z 換成 let z = x+y; 呢,也是正常執行和編譯的,這是由於編譯器自動把 y 解引用了,

impl<'a,'b> Add<&'a i32> for &'b i32

fn add(self, other: &'a i32) -> >::Output

相似於如何使用 Deref trait 重載不可變引用的 * 運算符,Rust 提供了 DerefMut trait 用於重載可變引用的 * 運算符。

Rust 在發現類型和 trait 實現知足三種狀況時會進行解引用強制多態:

當 T: Deref 時從 &T 到 &U。

當 T: DerefMut 時從 &mut T 到 &mut U。

當 T: Deref 時從 &mut T 到 &U。

頭兩個狀況除了可變性以外是相同的:第一種狀況代表若是有一個 &T,而 T 實現了返回 U 類型的 Deref,則能夠直接獲得 &U。第二種狀況代表對於可變引用也有着相同的行爲。

最後一個狀況有些微妙:Rust 也會將可變引用強轉爲不可變引用。可是反之是 不可能 的:不可變引用永遠也不能強轉爲可變引用。由於根據借用規則,若是有一個可變引用,其必須是這些數據的惟一引用(不然程序將沒法編譯)。將一個可變引用轉換爲不可變引用永遠也不會打破借用規則。將不可變引用轉換爲可變引用則須要數據只能有一個不可變引用,而借用規則沒法保證這一點。所以,Rust 沒法假設將不可變引用轉換爲可變引用是可能的

做者:zqliang 連接:https://hacpai.com/article/1540173433079 來源:黑客派 協議:CC BY-SA 4.0 https://creativecommons.org/licenses/by-sa/4.0/

相關文章
相關標籤/搜索