1. rust中 if else 語句是表達式 它一定返回一個值,所以可以將其賦值給一個變量。比如:
let codition = true;
let x = if condition {5} else {6};
2. rust 函數體 可以用return x;返回值;也可以在最后一行用一個表達式來表示要返回的值;使用"->"表示函數返回值的類型 比如:
fn five()->i32 {
5
}
fn main(){
let x= five();
println!("The value of x is: {x}");
}
3. loop 循環 。可以使用 break 跳出循環 ,continue 進入下次循環。可以使用break 表達式,為loop循環返回值。可以使用 ’my_loop_label 寫在loop關鍵字前,用來表示一個這樣名稱的標簽,然后在作用域范圍內例用 break my_loop_label 跳出這個指定的loop循環。如下代碼:
let result = loop{
break 5;
}
'my_loop_label loop{
loop{
break 'my_loop_label;//直接結束外層循環
}
}
4. for 循環。 for 元素 in 集合{...};
let array = [1,2,3,4];
for element in array{
println("element is {element}");
}
4.1 for循環常和 Range 類型結合使用。Range是一個用圓括號和..來表示一個指定范圍內的整數集合的類型,比如(1..4)表示1,2,3 即包含前面的不包含后面的。
for element in (1..5).rev(){
println("{element}");//打印出4 3 2 1
}
5.Rust的所有權機制
Box的所有者來管理堆內存釋放
Rust會自動釋放Box的堆內存
Rust內存釋放機制
如果一個變量擁有一個Box(即該Box的所有權人是這個變量且僅是這個變量),當rust釋放變量的frame(棧楨)時,Rust也會釋放Box的堆(Heap)內存
Rust中,像Vec、String、HashMap等集合類型,都使用了Box
移動堆數據原則(所有權轉移原則)
如果一個變量x將堆內存Heap所有權轉移給另一個變量y,那么在移動后,變量x就不能再使用。
5.2 引用(引用是沒有所有權的指針)
使用 "&" 符號加變量名的方式,用在函數形參中,這就是表示要為該函數傳遞一個引用類型的參數。引用是沒有所有權的。
注意下圖中,引用的本質,引用g1,g2指向了擁有所有權的變量m1,m2上,并不是直接指向堆。所以當引用超出作用范圍時,并不會釋放堆內存。

5.2.1 輸出一個變量及其引用在棧內存上的地址的示例:
let a = String::from("Hello");
let reference_a = &a;
let address_in_reference_a = reference_a as *const String;
println!("a:{}",a);
println!("&a{{:p}},即變量a在Stack上的內存地址:{:p}",&a);
println!("reference_a:{}",reference_a);
println!("address_in_reference_a{{:p}},即reference_a的值的內容:{:p}",address_in_reference_a);
println!("&reference_a{{:p}},即變量reference_a在Stack上的內存地址:{:p}",&reference_a);
以下為輸出結果:
a:Hello
&a{:p},即變量a在Stack上的內存地址:0x9bab8ff858
reference_a:Hello
address_in_reference_a{:p},即reference_a的值的內容:0x9bab8ff858
&reference_a{:p},即變量reference_a在Stack上的內存地址:0x9bab8ff870
- 以下代碼打印出來的結果都是 hello world
let m = String::from("hello world");
println!("{}",m);
println!("{}",&m);
println!("{}",&&m);
5.2.2 解引用
解引用指針以方問數據,解引用運算符:* 看下圖:

5.2.3 rust所有權機制設計的一些目的和手段
-
Rust中經常在【成員.方法名()】的用法中進行隱式的引用或解引用,看下圖:
![image]()
-
別名(堆內存的無所有權的直接引用者)和可變性不可同時存在(本質的意思是說不允許某個引用修改了它指向的堆上的數據但別的引用卻不知道。避免空指針、保障線程安全)
換句話說:數據不應同時被別名引用而又具有可變性
比如下圖闡述了一段會造成空指針問題的代碼:
![image]()
但是,可以通過間接方式(注意,這和別名引用不同),把變量(指向堆內存的)的引用賦給多個變量的方式來間接讓多個變量訪問同一塊堆內存數據并且原變量還具有可變性,比如下圖代碼:
![image]()
5.3 rust確保引用安全性的底層保障手段--借用檢查器,數據在編繹器底層時被細分為三種不同的權限(讀、寫、擁有【移動、釋放】)

下面是一個數據在被創建引用時,各變量自動獲得和失去三種權限的一個動態變化情況:
在創建了另一個別名num后數,v同時失去了W和O的權限,只保留了R的權限。在打印那一語句執行完后,num及*num隨即失去了三種權限,同時三種權限歸還給了變量v。
而最后一行執行完后,當數據不再被后面代碼使用到,則v立即失去三種權限,一旦數據所有者變量v失去數據所有權,則棧內存被釋放的同時堆上的數據也被立即釋放。個人體會:這種設計得以堆內存的數據隨時為被釋放做好準備,體現了Rust是高性能的語言高在了哪里。

以又是一個示例演練。

猜想:在執行完第二個語句后,x會重新獲得堆數據的所有權,但是如果這之后沒有再引用到變量x,則x同時會被釋放棧和它指向的堆上的數據的內存。
5.4 權限定義于哪里?權限是定義在“位置”(Places)上的,任何可以放在賦值符號左邊的位置都可以獲得和改變權限。也包括它們的組合
比如:變量、解引用、數組元素、元組和結構體的成員訪問,以及它們的組合比如:*((*a)[0].field1)
(個人理解不如把它們統稱為“數據訪問者”,它引發自己或其他數據訪問者權限狀態改變的改變 Trigger)
為什么隨者位置的不再使用,“位置”會失去所有權?因為權限是互斥的。(個人闡述為隨者數據訪問者的先后觸發權限改變,后觸發者會改變前面觸發者的權限狀態,有時就是讓前面觸發者失去某些權限)如下圖:

5.5 借用檢查器的工作原理
借用檢查器能發現權限違規。Rust在借用檢查器里使用RWO等權限。借用檢查器查找涉及引用的潛在不安全操作。下圖簡單示意了借用檢查器的工作原理:

可變引用可能會臨時降級為只讀,如下圖:

權限在引用生命周期結束時被返回,如下圖:

如果有if else等分支控制語句,也是這樣,一個引用生命周期開始和結束,都會影響到期他數據訪問者的權限:

5.6 生命周期概念的前置背景
以下代碼一和代碼二,其函數無法通過編繹,提示缺少生命周期說明符。
代碼一:(以下代碼,從函數的兩個輸入參數無法確定函數的返回值的生命周期【一般情況下,出參和入參生命周期一致】)

代碼二:(因為按照前面所學,在函數返回時a早已經超出生命周期而被釋放了)
fn return_a_string()->&String{
let a = String::from("hello");
let b = &a;
return b;
}
代碼三:(n是分配在棧上的值類型變量,在incr函數內部,m會在棧上創建,其值為n的地址,*m即對m解引用的結果就是n的值。該代碼最終輸出2)
fn incr(m: &mut i32) {
*m += 1;
}
let mut n=1;
incr(&mut n);
println!("{}",n);



浙公網安備 33010602011771號