學習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/31559985/viewspace-2739853/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 結構體學習結構體
- rust學習六、簡單的struct結構RustStruct
- GO 學習筆記->結構體Go筆記結構體
- Golang 學習——結構體 struct (一)Golang結構體Struct
- Golang 學習——結構體 struct (二)Golang結構體Struct
- go語言學習-結構體Go結構體
- 【CUDA學習】GPU硬體結構GPU
- struct 結構體 -Go 學習記錄Struct結構體Go
- Oracle體系結構學習筆記Oracle筆記
- golang 學習之路之 struct 結構體GolangStruct結構體
- JVM學習(一)——記憶體結構JVM記憶體
- ARM學習之中斷體系結構
- ASM學習筆記_體系結構ASM筆記
- 關於結構體型別的學習結構體型別
- 【C#學習筆記】結構體使用C#筆記結構體
- ARM學習之時鐘體系結構
- 【CUDA學習】結構體指標複製結構體指標
- DG學習筆記(2)_體系結構筆記
- Hive學習筆記 1 Hive體系結構Hive筆記
- Object C學習筆記20-結構體Object筆記結構體
- Linux核心學習—— 1核心體系結構Linux
- 資料結構學習之樹結構資料結構
- 資料結構學習資料結構
- 全面學習robotframework框架二:整體理解框架結構Framework框架
- 層模式——面向模式體系結構學習筆記模式筆記
- rust 模組組織結構Rust
- Rust程式設計與專案實戰-結構體Rust程式設計結構體
- 學習Rust 函式Rust函式
- 學習Rust 迴圈Rust
- Rust 學習筆記Rust筆記
- 深度學習與圖神經網路學習分享:Transformer 整體結構深度學習神經網路ORM
- yangwenmai/learning-rust: Rust 學習之路AIRust
- 009 通過連結串列學習Rust之IntoIterRust
- 009 透過連結串列學習Rust之IntoIterRust
- Go語言學習筆記 - PART7 - 結構體Go筆記結構體
- C語言學習筆記:結構體與指標C語言筆記結構體指標
- STM32F103的CAN結構體學習結構體
- Solidity語言學習筆記————15、結構體StructSolid筆記結構體Struct