RUST 學(xué)習(xí)日記 第5課 ——變量和常量

說些題外話,有些同學(xué)認為前面那么點內(nèi)容,啰啰嗦嗦的講了四節(jié),其實不然。本系列課程也是適合0基礎(chǔ)的同學(xué),如果您是Rust大神,那么可以忽略本系列的文章。還有學(xué)習(xí)一門編程語言要搞明白是為什么,不能只學(xué)習(xí)表面?;A(chǔ)一旦打好,學(xué)習(xí)任何語言都會覺得很容易。俗話說,萬事開頭難,一旦前面做好鋪墊,那么后面再難也難不住你。當然本人水平有限,錯誤和不足之處在所難免,處理問題也有不妥之處,敬請各位大佬,專家批評改正。
0x00 開篇
上一節(jié)咱們了解了Rust的常用規(guī)范,算是入鄉(xiāng)隨俗了。那么從今天開始就要正式進入Rust的學(xué)習(xí)了。該系列課程預(yù)計100課左右,大致將分為基礎(chǔ),進階,算法,實戰(zhàn)四大部分,甚至?xí)?。課程將會由淺入深的非常細致的講解Rust,帶你深入了解Rust。該系列教程所用的Rust版本是1.52.1(截至目前的最新版本)。
0x01 了解變量
Rust語言的變量是一種綁定語義,相當于是把一個變量名和一個值綁定在一起,從而建立起了關(guān)聯(lián)關(guān)系,類似于鍵值對。為了安全性的考慮,Rust的變量默認是不可以改變的,當然Rust也提供了另一種變量——可變變量。如果你了解過其它語言,你會發(fā)現(xiàn)Rust變量的設(shè)計與其它語言還是不同的。
0x02 命名規(guī)范
Rust變量名可以由字母,數(shù)字或者下劃線組成。同時還有以下3個限制條件:
- 不能以數(shù)字開頭
- 字母區(qū)分大小寫
- 不能只有下劃線
PS:關(guān)于下劃線,在Rust中式一種標識符,代表“忽略這個變量”,這里僅了解即可,后續(xù)章節(jié)會詳細介紹。
0x03 不可變變量(Immutable)
在Rust中是通過let關(guān)鍵字來聲明變量的,變量遵循先聲明后使用的原則。確切的說應(yīng)該是使用let將值綁定到變量。Rust 通過靜態(tài)類型確保類型安全。變量綁定可以在聲明時說明類型,當然也可以不說明類型,編譯器則將會從上下文推導(dǎo)出變量的類型。示例代碼如下:
fn main() {
// 每次聲明變量時,注意變量命名規(guī)范
// 聲明整數(shù)
let a = 5;
// 布爾值
let b1= true;
// 字符串
let _c = "zhangsan";
// 浮點數(shù)
let d_1 = 123.3;
dbg!(a);
dbg!(b1);
dbg!(_c);
dbg!(d_1);
}
0x04 可變變量(Mutable)
使用let關(guān)鍵字聲明的變量是不可改變的。如果你試圖改變它值,編譯器會報錯。Cannot assign twice to immutable variable [E0384]
let x = 5;
// 再次賦值會報錯
x = 15;
這時,如果你想重新對變量賦值,則需要使用mut關(guān)鍵字,告訴編譯器這個變量是可以重新賦值的。
// 使用mut關(guān)鍵字聲明變量
let mut y = 5;
// 編譯器不會報錯
y = 15;
單從變量賦值這一點,咱們就可以看出Rust的安全性了。增加mut關(guān)鍵字,可以傳達該變量允許被更改的意圖,使得代碼可讀性增強,也容易維護。
0x05 變量遮蔽 (Shadowing)
在Rust中,允許在同一代碼塊中使用let關(guān)鍵字多次聲明同名變量,如果多次聲明同一變量,則后者會覆蓋前者的值,因此前者的值將無法再去訪問,多次覆蓋則以最后一次的值為準——這就是變量遮蔽,有時也叫做變量重定義。
// 變量遮蔽
let m = 1;
let m = 2.3;
let m = "張三";
let mut m = 4;
let m = 5;
dbg!(m);
最后輸出結(jié)果是:
[src\main.rs:37] m = 5
變量遮蔽的實質(zhì)是同let聲明了一個新的變量,但是巧合的是與之前聲明的變量重名了。變量遮蔽有以下幾個特點:
- 它們是完全不相同的變量
- 它們所處的內(nèi)存空間不相同
- 它們的值的類型可以不相同
- 它們的值可以不相同
- 可以作用于不可變變量,也可以作用于可變變量
- 不可以作用于
static變量 - 不可以作用于
const常量
在C,C++,Java等常見的語言中是不存在變量遮蔽的,因此變量遮蔽常用于一些特殊場景,將會在后續(xù)章節(jié)介紹。
0x06 常量(Const)
常量是指綁定到一個標識符且不允許改變的值,其一旦定義后將沒有任何方法能夠改變它。它還有一個非常重要的特點——常量會在編譯時被復(fù)制到使用的地方(類似于C語言的#define)。 當然,這種復(fù)制也會發(fā)生在外部包被編譯的場合。其聲明語法如下:
// 命名規(guī)則:變量名全部大寫
// 多單詞組合使用下劃線分割,如:MIN_VALUE
// 必須指定變量的數(shù)據(jù)類型
// const PI = 3.141592653; [X] 錯誤寫法
const PI : f64 = 3.141592653;
聲明規(guī)則:
- 使用
const關(guān)鍵字聲明 - 常量的名稱通常都是全部采用大寫字母,如遇到多單詞組合,則使用下劃線分割,如:MIN_VALUE
- 必須指定變量的數(shù)據(jù)類型(關(guān)于數(shù)據(jù)類型將在下節(jié)介紹)
看到這里,心中是否存在疑問——前面說的不可變變量的值不能被更改,常量的值也不能被更改,那么它們有什么區(qū)別呢?當然上面也提到了部分區(qū)別,下面整理下完整答案。
- 常量必須使用
const關(guān)鍵字聲明,且必須注明值的類型,不可變變量使用let關(guān)鍵字聲明。 - 不可變變量可以通過變量遮蔽的方式,讓其值改變。實質(zhì)上是新的變量,只是同名而已。然而常量則沒有變量遮蔽的概念,無法重復(fù)定義。常量一旦定義,就永遠不能變更和重新賦值。
- 可以在任何作用域中聲明常量。在聲明它的作用域中,常量在整個生命周期(關(guān)于生命周期將在后續(xù)章節(jié)介紹)中都是有效的。
- 常量智能被賦值為常量表達式或者數(shù)學(xué)表達式。不能是函數(shù)的返回值,或者是其他在運行時才能確定的值。然而不可變變量則不受限制。
0x07 靜態(tài)變量——又稱全局變量(Static)
靜態(tài)變量和常量很相似,但是在一個程序中,靜態(tài)變量擁有精確固定的內(nèi)存地址,對于靜態(tài)變量的所有引用都指向相同的內(nèi)存地址。靜態(tài)變量也存在生命周期,但是其生命周期在程序中是最長的。靜態(tài)變量不會在程序結(jié)束時調(diào)用drop函數(shù)。官方文檔是這樣說的:
A static item is similar to a constant, except that it represents a precise memory location in the program. All references to the static refer to the same memory location. Static items have the lifetime, which outlives all other lifetimes in a Rust program. Static items do not call
dropat the end of the program.
靜態(tài)變量是可以用mut來修飾的,一旦靜態(tài)變量可變,就會出現(xiàn)多線程同時訪問的場景,從而引發(fā)內(nèi)存不安全的問題,因此對于static mut聲明的變量必須在unsafe塊中進行定義(有關(guān)unsafe的內(nèi)容將在后續(xù)章節(jié)介紹)。
靜態(tài)變量和常量的應(yīng)用場景:
- 數(shù)據(jù)占有內(nèi)存比較大的場合,推薦使用靜態(tài)變量。
- 程序需要變量的地址屬性的情況下,推薦使用靜態(tài)變量。
- 變量需要是可變的情況下,推薦使用靜態(tài)變量。
- 其它場景常量優(yōu)于靜態(tài)變量。
fn main (){
static IP: &str = "111.111.111.111";
static mut NAME : &str = "zhangsan";
dbg!(IP);
unsafe {
dbg!(NAME);
}
}
0x08 本節(jié)源碼
005 · StudyRust - 碼云 - 開源中國 (gitee.com)
下節(jié)預(yù)告——了解下Rust的常見基本數(shù)據(jù)類型