學習Rust 結構體
導讀 | Rust 語言是一種高效、可靠的通用高階語言。其高效不僅限於開發效率,它的執行效率也是令人稱讚的,是一種少有的兼顧開發效率和執行效率的語言。 |
Rust 中的結構體(Struct)與元組(Tuple)都可以將若干個型別不一定相同的資料捆綁在一起形成整體,但結構體的每個成員和其本身都有一個名字,這樣訪問它成員的時候就不用記住下標了。元組常用於非定義的多值傳遞,而結構體用於規範常用的資料結構。結構體的每個成員叫做"欄位"。
這是一個結構體定義:
struct Site { domain: String, name: String, nation: String, found: u32 }
注意:如果你常用 C/C++,請記住在 Rust 裡 struct 語句僅用來定義,不能宣告例項,結尾不需要 ; 符號,而且每個欄位定義之後用 , 分隔。
Rust 很多地方受 JavaScript 影響,在例項化結構體的時候用 JSON 物件的 key: value 語法來實現定義:
例項
let runoob = Site { domain: String::from("), name: String::from("RUNOOB"), nation: String::from("China"), found: 2013 };
如果你不瞭解 JSON 物件,你可以不用管它,記住格式就可以了:
結構體類名 { 欄位名 : 欄位值, ... }
這樣的好處是不僅使程式更加直觀,還不需要按照定義的順序來輸入成員的值。
如果正在例項化的結構體有欄位名稱和現存變數名稱一樣的,可以簡化書寫:
例項
let domain = String::from("); let name = String::from("RUNOOB"); let runoob = Site { domain, // 等同於 domain : domain, name, // 等同於 name : name, nation: String::from("China"), traffic: 2013 };
有這樣一種情況:你想要新建一個結構體的例項,其中大部分屬性需要被設定成與現存的一個結構體屬性一樣,僅需更改其中的一兩個欄位的值,可以使用結構體更新語法:
let site = Site { domain: String::from("), name: String::from("RUNOOB"), ..runoob };
注意:..runoob 後面不可以有逗號。這種語法不允許一成不變的複製另一個結構體例項,意思就是說至少重新設定一個欄位的值才能引用其他例項的值。
有一種更簡單的定義和使用結構體的方式:元組結構體。
元組結構體是一種形式是元組的結構體。
與元組的區別是它有名字和固定的型別格式。它存在的意義是為了處理那些需要定義型別(經常使用)又不想太複雜的簡單資料:
struct Color(u8, u8, u8); struct Point(f64, f64); let black = Color(0, 0, 0); let origin = Point(0.0, 0.0);
"顏色"和"點座標"是常用的兩種資料型別,但如果例項化時寫個大括號再寫上兩個名字就為了可讀性犧牲了便捷性,Rust 不會遺留這個問題。元組結構體物件的使用方式和元組一樣,透過 . 和下標來進行訪問:
例項
fn main() { struct Color(u8, u8, u8); struct Point(f64, f64); let black = Color(0, 0, 0); let origin = Point(0.0, 0.0); println!("black = ({}, {}, {})", black.0, black.1, black.2); println!("origin = ({}, {})", origin.0, origin.1); }
執行結果:
black = (0, 0, 0) origin = (0, 0)
結構體必須掌握欄位值所有權,因為結構體失效的時候會釋放所有欄位。
這就是為什麼本章的案例中使用了 String 型別而不使用 &str 的原因。
但這不意味著結構體中不定義引用型欄位,這需要透過"生命週期"機制來實現。
但現在還難以說明"生命週期"概念,所以只能在後面章節說明。
輸出結構體
除錯中,完整地顯示出一個結構體例項是非常有用的。但如果我們手動的書寫一個格式會非常的不方便。所以 Rust 提供了一個方便地輸出一整個結構體的方法:
例項
#[derive(Debug)] struct Rectangle { width: u32, height: u32, } fn main() { let rect1 = Rectangle { width: 30, height: 50 }; println!("rect1 is {:?}", rect1); }
如第一行所示:一定要匯入除錯庫 #[derive(Debug)] ,之後在 println 和 print 宏中就可以用 {:?} 佔位符輸出一整個結構體:
rect1 is Rectangle { width: 30, height: 50 }
如果屬性較多的話可以使用另一個佔位符 {:#?} 。
輸出結果:
rect1 is Rectangle { width: 30, height: 50 }
方法(Method)和函式(Function)類似,只不過它是用來操作結構體例項的。
如果你學習過一些物件導向的語言,那你一定很清楚函式一般放在類定義裡並在函式中用 this 表示所操作的例項。
Rust 語言不是物件導向的,從它所有權機制的創新可以看出這一點。但是物件導向的珍貴思想可以在 Rust 實現。
結構體方法的第一個引數必須是 &self,不需宣告型別,因為 self 不是一種風格而是關鍵字。
計算一個矩形的面積:
例項
struct Rectangle { width: u32, height: u32, } impl Rectangle { fn area(&self) -> u32 { self.width * self.height } } fn main() { let rect1 = Rectangle { width: 30, height: 50 }; println!("rect1's area is {}", rect1.area()); }
輸出結果:
rect1's area is 1500
請注意,在呼叫結構體方法的時候不需要填寫 self ,這是出於對使用方便性的考慮。
一個多引數的例子:
例項
struct Rectangle { width: u32, height: u32, } impl Rectangle { fn area(&self) -> u32 { self.width * self.height } fn wider(&self, rect: &Rectangle) -> bool { self.width > rect.width } } fn main() { let rect1 = Rectangle { width: 30, height: 50 }; let rect2 = Rectangle { width: 40, height: 20 }; println!("{}", rect1.wider(&rect2)); }
執行結果:
false
這個程式計算 rect1 是否比 rect2 更寬。
之所以"結構體方法"不叫"結構體函式"是因為"函式"這個名字留給了這種函式:它在 impl 塊中卻沒有 &self 引數。
這種函式不依賴例項,但是使用它需要宣告是在哪個 impl 塊中的。
一直使用的 String::from 函式就是一個"關聯函式"。
例項
#[derive(Debug)] struct Rectangle { width: u32, height: u32, } impl Rectangle { fn create(width: u32, height: u32) -> Rectangle { Rectangle { width, height } } } fn main() { let rect = Rectangle::create(30, 50); println!("{:?}", rect); }
執行結果:
Rectangle { width: 30, height: 50 }
貼士:結構體 impl 塊可以寫幾次,效果相當於它們內容的拼接!
結構體可以值作為一種象徵而無需任何成員:
struct UnitStruct;
我們稱這種沒有身體的結構體為單元結構體(Unit Struct)。
原文來自:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69955379/viewspace-2739578/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 結構體學習結構體
- rust學習六、簡單的struct結構RustStruct
- GO 學習筆記->結構體Go筆記結構體
- Golang 學習——結構體 struct (一)Golang結構體Struct
- Golang 學習——結構體 struct (二)Golang結構體Struct
- go語言學習-結構體Go結構體
- JVM學習(一)——記憶體結構JVM記憶體
- golang 學習之路之 struct 結構體GolangStruct結構體
- Oracle體系結構學習筆記Oracle筆記
- struct 結構體 -Go 學習記錄Struct結構體Go
- 關於結構體型別的學習結構體型別
- Linux核心學習—— 1核心體系結構Linux
- 資料結構學習之樹結構資料結構
- 資料結構學習資料結構
- Rust程式設計與專案實戰-結構體Rust程式設計結構體
- 全面學習robotframework框架二:整體理解框架結構Framework框架
- Solidity語言學習筆記————15、結構體StructSolid筆記結構體Struct
- STM32F103的CAN結構體學習結構體
- 深度學習與圖神經網路學習分享:Transformer 整體結構深度學習神經網路ORM
- 009 透過連結串列學習Rust之IntoIterRust
- 010 透過連結串列學習Rust之IterRust
- 011 透過連結串列學習Rust之IterMutRust
- 009 通過連結串列學習Rust之IntoIterRust
- 010 通過連結串列學習Rust之IterRust
- 011 通過連結串列學習Rust之IterMutRust
- yangwenmai/learning-rust: Rust 學習之路AIRust
- 資料結構學習--連結串列資料結構
- 資料結構學習總結--圖資料結構
- C語言學習筆記:結構體與指標C語言筆記結構體指標
- Go語言學習筆記 - PART7 - 結構體Go筆記結構體
- 015 透過連結串列學習Rust之使用ArcRust
- 015 通過連結串列學習Rust之使用ArcRust
- Rust 學習筆記Rust筆記
- 學習Rust 函式Rust函式
- 學習Rust 迴圈Rust
- rust 模組組織結構Rust
- 資料結構學習心得資料結構
- PostgreSQL 資料庫學習 - 1.資料庫體系結構之儲存結構SQL資料庫