Rust for循環語法糖背後的API場景分析
Rust中for循環實質上是一個語法糖,in後面的對象要求是一個迭代器,for循環就是對這個迭代器循環調用next,而in前面的名稱就是每一次迭代後返回的結果,如果next返回Option::None則退出循環。瞭解這一點後我們可以自己編寫自己的迭代器類型,然後使用for循環進行迭代。
rust有三種for循環,分別用於不同的場景。
1.拿走所有權的for循環
形式如:for item in collection
(集合或容器類型)會拿走collection的所有權(ownership)
。
fn main() { let collection: Vec<i32> = vec![1, 2, 4, 6, 9]; // 註意這兒的item類型是i32 for item in collection { println!("item:{}", item); } // for循環之後,不能再使用collection,因為collection的所有權已經被拿走,且在for循環後collection已經被drop掉瞭 // println!("collection:{:?}", collection); }
因為rust編譯器會將for item in collection
替換成for item in IntoIterator::into_iter(collection)
:
fn main() { let collection: Vec<i32> = vec![1, 2, 4, 6, 9]; // rust中的into_開頭的方法一般情況下都會拿走參數的所有權 let iter = IntoIterator::into_iter(collection); // 從這兒開始,collection已經不能再被使用,因為collection的所有權被轉移到into_iter方法中,當方法執行完,collection就被drop掉瞭 // println!("collection:{:?}", collection); // 如果這兒使用collection就會編譯報錯 for item in iter{ println!("item:{}", item); } }
正如Rust官網https://doc.rust-lang.org/std/iter/trait.IntoIterator.html上說的:One benefit of implementing IntoIterator
is that your type will work with Rust’s for
loop syntax.,即實現IntoIterator trait能夠讓你自定義類型在for循環中使用。
Vec正是實現瞭IntoIterator,所以才可以在for循環中使用的:
2.隻讀for循環
形式如:for item in &collection
,不會拿走collection的所有權,隻會獲取它的不可變引用:
fn main() { let collection: Vec<i32> = vec![1, 2, 4, 6, 9]; // 註意這兒item的類型是&i32,即它是對collection中元素的不可變引用 for item in &collection { println!("item:{}", item); } println!("collection after for loop:{:?}", collection); }
因為rust會將for item in &collection
替換成for item in collection.iter()
:
fn main() { let collection: Vec<i32> = vec![1, 2, 4, 6, 9]; // 註意這兒item的類型是&i32,即它是對collection中元素的不可變引用 for item in collection.iter() { // 等價於for item in (&collection).iter() { println!("item:{}", item); } println!("collection after for loop:{:?}", collection); }
迭代完集合中的元素後,集合還可以繼續使用。
3.讀寫for循環
形式如:for item in &mut collection
,不會拿走collection的所有權,隻會獲取它的可變引用:
fn main() { // 註意,為瞭修改collection中的元素,collection本身必須聲明為mut let mut collection: Vec<i32> = vec![1, 2, 4, 6, 9]; // 註意這兒item的類型是&mut i32,即它是對collection中元素的可變引用 for item in &mut collection { // 通過*對可變引用進行解引用,從而可以修改引用指向的值 *item = *item +1; println!("item:{}", item); } println!("collection after for loop:{:?}", collection); }
上面的程序運行輸出:
item:2
item:3
item:5
item:7
item:10
collection after for loop:[2, 3, 5, 7, 10]
實現瞭對集合元素的修改。
因為rust會將for item in &mut collection
替換成for item in collection.iter_mut()
:
fn main() { // 註意,為瞭修改collection中的元素,collection本身必須聲明為mut let mut collection: Vec<i32> = vec![1, 2, 4, 6, 9]; // 註意這兒item的類型是&mut i32,即它是對collection中元素的可變引用 for item in collection.iter_mut() { // 等價於for item in (&mut collection).iter_mut() { // 通過*對可變引用進行解引用,從而可以修改引用指向的值 *item = *item +1; println!("item:{}", item); } println!("collection after for loop:{:?}", collection); }
參考資料:
1.《Rust實戰》(Rust In Action)
到此這篇關於Rust for循環語法糖背後的API的文章就介紹到這瞭,更多相關Rust for循環內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Rust語言從入門到精通系列之Iterator迭代器深入詳解
- 深入瞭解Rust 結構體的使用
- 關於Rust 使用 dotenv 來設置環境變量的問題
- Rust 入門之函數和註釋實例詳解
- 使用Cargo工具高效創建Rust項目