Struct的基本使用
使用struct
關鍵字定義Struct類型。
具名Struct
具名Struct(named Struct)表示有字段名稱的Struct。Struct的字段(Field)也可以稱為Struct的屬性(Attribute)。
例如,定義一個名為Person的Struct結構體,Person包含三個屬性,分別是name、age和email,每個屬性都需要指定數據類型,這樣可以限制各屬性允許存放什麼類型的數據。
#![allow(unused)] fn main() { struct Person{ name: String, age: u32, email: String, // 最後一個字段的逗號可省略,但建議保留 } }
定義Struct後,可創建Struct的實例對象,為其各個屬性指定對應的值即可。
例如,構造Person結構體的實例對象user1,
#![allow(unused)] fn main() { let user1 = Person { name: String::from("junmajinlong"), email: String::from("[email protected]"), age: 23, }; }
創建user1實例對象後,可以通過user1.name
訪問它的name字段的值,user1.age
訪問它的age字段的值。
以下是一段完整的代碼:
struct Person{ name: String, age: u32, email: String, } fn main(){ let user1 = Person{ name: String::from("junmajinlong"), email: String::from("[email protected]"), age: 23, }; // 訪問user1實例name字段、age字段和email字段的值 println!( "name: {}, age: {}, email: {}", user1.name, user1.age, user1.email ); }
構造struct的簡寫方式
當要構造的Struct實例的字段值來自於變量,且這個變量名和字段名相同,則可以簡寫該字段。
struct Person{ name: String, age: u32, email: String, } fn main(){ let name = String::from("junmajinlong"); let email = String::from("[email protected]"); let user1 = Person{ name, // 簡寫,等價於name: name email, // 簡寫,等價於email: email age: 23, }; }
有時候會基於一個Struct實例構造另一個Struct實例,Rust允許通過..xx
的方式來簡化構造struct實例的寫法:
#![allow(unused)] fn main() { let name = String::from("junmajinlong"); let email = String::from("[email protected]"); let user1 = Person{ name, email, age: 23, }; let mut user2 = Person{ name: String::from("gaoxiaofang"), email: String::from("[email protected]"), ..user1 }; }
上面的..user1
表示讓user2借用或拷貝user1的某些字段值,由於user2中已經手動定義了name和email字段,因此..user1
只借用了user1的age字段,即user2.age
也是23。
注意,如果..base
借用於base的字段是可Copy的,那麼在借用時會自動Copy,這樣在借用字段之後,base中的字段仍然有效。但如果借用的字段不是Copy的,那麼在借用時會將base中字段的所有權轉移走,使得base中的該字段無效。
例如,同時借用user1中的age字段和email字段,由於age是i32類型,是Copy的,所以user1.age
仍然可用,但由於String類型不是Copy的,所以user1.email
不可用。
#![allow(unused)] fn main() { let name = String::from("junmajinlong"); let email = String::from("[email protected]"); let user1 = Person{ name, email, age: 23, }; let mut user2 = Person{ name: String::from("gaoxiaofang"), ..user1 }; // 報錯,user1.email字段值的所有權已借給user2 // println!("{}", user1.email); // println!("{}", user1); // 報錯 println!("{}", user1.name); // 正確 println!("{}", user1.age); // 正確 }
如果確實要借用user1的email屬性,可以使用..user1.clone()
先拷貝堆內存中的user1,這樣就不會借用原始的user1中的email所有權。
#![allow(unused)] fn main() { let user2 = Person{ name: String::from("ggg"), ..user1.clone() } }
tuple struct
除了named struct外,Rust還支持沒有字段名的struct結構體,稱為元組結構體(tuple struct)。
例如:
#![allow(unused)] fn main() { struct Color(i32, i32, i32); struct Point(i32, i32, i32); let black = Color(0, 0, 0); let origin = Point(0, 0, 0); }
black和origin值的類型不同,因為它們是不同的結構體的實例。在其他方面,元組結構體實例類似於元組:可以將其解構,也可以使用.
後跟索引來訪問單獨的值,等等。
unit-like struct
類單元結構體(unit-like struct)是沒有任何字段的空struct。
#![allow(unused)] fn main() { struct St; }