Rust 從函數式語言中借鑑了 let 關鍵字建立變量。 Let 建立的變量通常稱爲綁定(Binding),它代表了標識符(Identifier)和值(value)之間創建的一種關聯關係。數組
Rust 中的表達式通常能夠分爲位置表達式(Place Expression)和值表達式(Value Expression)。安全
位置表達式即表示內存位置的表達式。分爲markdown
經過位置表達式能夠對某個數據單元的內存進行讀寫。主要是進行寫操做,也就是位置表達式能夠被賦值的緣由。函數
除了位置表達式之外的表達式就是值表達式。 值表達式通常值引用了某個存儲單元地址中的數據。至關於數據值,只能進行讀操做。spa
從語義角度講, 位置表達式表明了數據持久性數據,值表達式表明了臨時數據。位置表達式通常有持久狀態,值表達式通常爲字面量或爲表達式求值過鄭重建立的臨時值。指針
表達式的求值過程在不一樣的上下文中會有不一樣的結果。求值上下文也分爲位置上下文(Place Context)和值上下文(Value Context)code
a = b + c
其中 a 就是位置上下文除此之外都是值上下文。值表達式不能出如今位置上下文中。示例以下:orm
pub fn temp() -> i32 {
return 1;
}
fn main () {
let x = &temp(); // temp 函數調用是一個無效的位置表達式
temp() = *x; // error 報錯
}
複製代碼
函數 temp 的調用放到了賦值語句左邊的位置上下文中,此時編譯器報錯,由於 temp 函數調用的是一個無效的位置表達式,它是值表達式。索引
使用 let 關鍵字聲明的位置表達式默認不可變,爲不可變綁定,簡單來說,就 是 let 聲明的變量不可變,相似於 JavaScript 中的 const 關鍵字。ip
fn main () {
let a = 1; // a 不可變
// a = 2; immutable and error
let mut b = 2; // 增長可變聲明
b = 3;
}
複製代碼
經過 mut 關鍵字,能夠聲明可變的位置表達式,便可變綁定,可變綁定能夠正常修改和賦值。
從語義上來說,let 默認聲明的不可變綁定只能對相應的存儲單元進行讀取,而 let mut 聲明的可變綁定則是能夠對相應的存儲單元進行寫入的。
當位置表達式出如今值上下文中時,該表達式會把內存地址轉移給另一個位置表達式,這實際上是全部權轉移。
fn main () {
let place1 = "hello";
let place2 = "hello".to_string();
let other = place1;
println!("{:?}", other);
let other = place2;
println("{:?}", other) // error
}
複製代碼
上面代碼中使用 let 聲明瞭兩個綁定, place1 和 place2。而後將 place1 賦值給新的變量 other。 由於 place1 是一個位置表達式,出如今了賦值操做符的右側,即一個值上下文內,因此 place1 會將內存地址轉移給 other。同理 將 place2 複製給新聲明的 other ,place2 的內存地址一樣會轉移給 other。
第二次聲明 other 將 place2 地址賦值給 other 時,會出現報錯,意爲該處使用了已經移動的值,之因此會出現這種區別,實際上是和底層內存安全管理有關係。這兩種行爲雖然有差異,都是 Rust 爲了安全刻意爲之。
在語義上,每一個變量綁定實際上都擁有該存儲單元的全部權,這種轉移內存地址的行爲就是全部權(OwnerShip) 的轉移,在 Rust 中移動(Move)語義,那種不轉移的狀況其實是一種複製(Copy)語義。Rust 無 GC,因此徹底靠全部權來進行內存管理。
在開發中,通常不須要轉移全部權。Rust 提供了引用操做符(&),能夠直接獲取表達式的存儲單元地址,即內存爲止。能夠經過該內存位置對內存進行讀取。
fn main () {
let a = [1,2,3];
let b = &a; // 獲取內存地址,至關於指針
println!("{:p}", b);
let mut c = vec![1,2,3];
let d = &mut c;
d.push(4);
println!("{:?}", d);
}
複製代碼
上面代碼中,b 以 & 的方式獲取 a 的內存地址,這種方式不會引發全部權轉移,由於使用引用操做符已經將賦值表達式右側變成了位置上下文,它知識共享內存位置,經過 println! 宏指定{:p} 格式,能夠打印 b 的指針地址,也就是內存地址。
經過 let mut 聲明動態常數數組c ,經過 &mut 可獲取 c 的可變引用,賦值給 d, 對於 d 的 push 操做,插入新的元素 4。要獲取可變引用,必須先聲明可變綁定。
不管是&a 仍是 &mut c 都至關於對於 a 和 c 全部權的借用,由於 a 和 c 還依舊保留他們的全部權,因此引用也稱之爲借用。