Rust 變數必須先宣告,後使用。
對於區域性變數,常見是宣告語法為:
let variable : i32 = 100;
由於 Rust 是有自動推導型別功能的,所以後面的 :i32 是可以省略的。
區域性變數宣告一定是以 let 開頭,型別一定是跟在冒號 : 的後面。語法歧義更少,語法分析器更容易編寫。
Rust 宣告變數的特點:要宣告的變數前置,型別描述後置。
這是因為在變數宣告語句中,最重要的是變數本身,而型別其實是個附屬的額外描述,並非必不可少的部分。如果我們可以通過上下文環境由編譯器自動分析出這個變數的型別,那麼這個型別描述完全可以省略不寫。
PS:Rust 支援型別推導,在編譯器能夠推導型別的情況下,變數型別一般可以省略,但常數(const)和靜態變數(static)必須宣告型別。
Rust 從一開始就考慮了型別自動推導功能,因此型別後置的語法更加合適。
pattern destructure
比如將變數由唯讀變為可讀寫(mut宣告)
Rust 裡的合法識別符號(包括變數名、函數名、trait名等)必須由:
①、數位
②、字母
③、下劃線
注意:不能以數位開頭!!!
另外:要注意下劃線 _ 的特殊用法。
Rust 允許在同一個程式碼塊中宣告同樣名字的變數,後面宣告的變數會將前面宣告的變數「遮蔽」起來。
//變數遮蔽
fn variable_masking(){
let x = "123";
println!("{}",x);
let x = 1;
println!("{}",x);
}
注意:這樣做並不會產生記憶體安全問題,因為我們對這塊記憶體擁有完整的所有權,且此時並沒有任何其它參照指向這個變數,對這個變數的修改是完全合法的。
Rust的型別推導有兩種:
①、從變數宣告的當前語句中獲取資訊進行推導
②、通過上下文資訊進行推導
//型別推導
fn type_derivation(){
//1.1 沒有明確標出變數型別,但是通過字面量的字尾,編譯器知道x的型別是 u8
let x = 5u8;
//1.2 通過字面量值 1,編譯器知道y 的型別是 i32
let y = 1;
//1.3 建立一個動態陣列,但是沒有宣告陣列裡面是什麼型別
let mut vec = Vec::new();
//編譯器通過新增的元素 1 ,推匯出 vec 的實際型別是 Vec<i32>
vec.push(1);
println!("{}",x);
println!("{}",y);
println!("{:?}",vec);
}
通過 type 關鍵字給同一個型別起個別名。
//型別別名
fn type_alias(){
//將 i32 這種資料型別起別名為 int
type int = i32;
let x : int = 1;
println!("{}",x);
}
型別別名還可以用於泛型場景:
type Double
= (T,Vec );
那麼,以後使用 Double
Rust 宣告的變數預設是不可變的。
預設不可變,這是一個很重要的特性,它符合最小許可權原則,有助於我們寫出正確且健壯的程式碼。
// 變數不可變
fn variable_mut(){
let i = 123;
i = 2;
}
編譯報錯:
如果要使得變數可變,必須要用關鍵字 mut
宣告:
fn variable_mut(){
let mut i = 123;
i = 2;
}
當你使用 mut 卻沒有修改變數,Rust 編譯期會友好地報警,提示你移除不必要的 mut。
fn main() {
variable_mut();
}
// 變數不可變
fn variable_mut(){
let mut i = 123;
println!("{}",i);
}
編譯器警告:
Rust 中通過 static 關鍵字宣告靜態變數,如下:
static GLOBAL : i32 = 0;
static 宣告的變數的生命週期是整個程式,從啟動到退出,static 變數的生命週期永遠是 ‘static’,它佔用的記憶體空間也不會在執行過程中被回收。
這也是 Rust 中唯一宣告全域性變數的方法。
由於 Rust 非常注重記憶體安全,因此全域性變數的使用有很多限制:
①、全域性變數必須在宣告的時候馬上初始化(對應區域性變數可以先宣告不初始化,只需要保證使用的時候初始化就行了,我們可以這樣理解,全域性變數是寫在函數外面,而區域性變數是寫在函數內部,所以需要保證全域性變數宣告的時候就要初始化);
②、全域性變數的初始化必須是編譯期可確定的常數,不能包括執行期才能確定的表示式、語句和函數呼叫;
③、帶有 mut 修飾的全域性變數,在使用的時候必須使用 unsafe 關鍵字。
Rust 中通過 const 關鍵字宣告常數。如下:
const GLOBAL : i32 = 0;
①、使用 const 宣告的是常數,而不是變數。因此不允許使用 mut 關鍵字修飾這個變數繫結。
②、常數的初始化表示式也一定要是一個編譯期確定的常數,不能是執行期的值。
注意:const 和 static 最大的區別在於編譯器並不一定會給 const 常數分配記憶體空間,在編譯過程中,它很可能會被內聯優化。
型別沒有預設建構函式,變數值沒有「預設值」
fn main() {
let x : i32;
println!("{}",x);
}
這個很容易理解,常數是不可變的,mut 表示可變,放一起語意衝突了。
//mut和 const 不能一起使用
fn const_mut_error(){
const mut i : i32 = 1;
println!("{}",i);
}