文章目錄
- Rust 定義與實例化結構體
- 5.1 結構體的定義與意義
- 5.2 結構體實例化
- 5.2.1 基本實例化
- 5.2.2 可變性規則
- 5.2.3 字段初始化簡寫
- 5.2.4 結構體更新語法
- 5.3 特殊結構體類型
- 5.3.1 元組結構體(Tuple Struct)
- 5.3.2 類單元結構體(Unit-Like Struct)
- 5.4 結構體的所有權與生命周期
- 5.4.1 所有權規則
- 5.4.2 引用字段與生命周期
- 5.5 最佳實踐與常見場景
- 5.6 應用示例
Rust 定義與實例化結構體
結構體(struct)是Rust中組織和封裝相關數據的核心工具。它通過命名字段將不同類型的數據組合成一個有意義的整體,提供比元組更清晰的語義和更強的類型安全性。本章將深入探討結構體的定義、實例化及高級技巧。
5.1 結構體的定義與意義
結構體使用 struct
關鍵字定義,包含字段名和類型聲明:
struct User { active: bool, username: String, email: String, sign_in_count: u64,
}
核心特點:
- 語義明確性:字段名(如
username
)直接描述數據含義,避免了元組依賴位置索引的歧義性。 - 類型安全:每個字段類型在編譯時確定,確保內存安全。
- 靈活性:實例化時字段順序無需與定義一致。
與元組的對比:
特性 | 結構體 | 元組 |
---|---|---|
字段訪問 | 點運算符(user.email ) | 索引(user.1 ) |
可讀性 | 高(命名字段) | 低(依賴位置) |
類型組合 | 支持異構類型 | 支持異構類型 |
5.2 結構體實例化
5.2.1 基本實例化
通過鍵值對為字段賦值:
let user1 = User { email: String::from("alice@example.com"), username: String::from("alice92"), active: true, sign_in_count: 1,
};
5.2.2 可變性規則
- 整體可變:使用
mut
聲明整個實例可變,所有字段均可修改:let mut user1 = User { /* ... */ }; user1.email = String::from("new_email@example.com"); // 合法修改
- 禁止部分可變:Rust不支持單獨標記某個字段可變(如
mut username
)。
5.2.3 字段初始化簡寫
當變量名與字段名相同時,可省略重復賦值:
fn build_user(email: String, username: String) -> User { User { email, // 等價于 email: email username, // 等價于 username: username active: true, sign_in_count: 1, }
}
此語法減少冗余代碼,提升可讀性。
5.2.4 結構體更新語法
使用 ..
從現有實例復制未顯式賦值的字段:
let user2 = User { email: String::from("bob@example.com"), ..user1 // 復制user1的其余字段
};
注意事項:
..user1
必須置于末尾。- 所有權轉移:若復制的字段包含所有權類型(如
String
),原實例的對應字段將失效:println!("{}", user1.username); // ? 錯誤!所有權已轉移至user2 println!("{}", user1.active); // ? 安全(bool實現Copy)
5.3 特殊結構體類型
5.3.1 元組結構體(Tuple Struct)
定義時僅聲明字段類型,無字段名:
struct Color(i32, i32, i32);
struct Point(i32, i32, i32); let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);
特點:
- 類型區分:
Color
和Point
是不同類型,即使字段類型相同。 - 訪問方式:通過索引(如
black.0
)或解構(let Color(r, g, b) = black;
)訪問字段。
5.3.2 類單元結構體(Unit-Like Struct)
無任何字段的結構體:
struct AlwaysEqual;
let subject = AlwaysEqual;
應用場景:
- 實現
trait
但無需存儲數據(如標記類型)。 - 泛型編程中的占位符。
5.4 結構體的所有權與生命周期
5.4.1 所有權規則
結構體默認擁有所有字段的所有權:
struct User { username: String, // 擁有數據所有權 email: String, // ...
}
優勢:結構體失效時自動釋放所有字段,避免內存泄漏。
5.4.2 引用字段與生命周期
若需在結構體中存儲引用,必須使用生命周期注解:
struct UserBorrowed<'a> { username: &'a str, // 引用外部數據 email: &'a str,
}
要求:引用的數據(如 String
變量)必須比結構體實例存活更久,否則導致懸垂引用。
5.5 最佳實踐與常見場景
- 數據封裝:將關聯數據(如用戶信息)組合為結構體,提升代碼可讀性。
- 類型安全抽象:用獨立結構體區分語義不同的數據類型(如
UserId(u64)
和OrderId(u64)
)。 - 構建模式:通過構造函數(如
User::new()
)封裝實例化邏輯。
下一章將涵蓋結構體方法(
impl
塊)和關聯函數,進一步擴展結構體的行為建模能力。
5.6 應用示例
struct User {username: String,email: String,sign_in_count: u64,active: bool,
}fn main() {let user1 = User {email: String::from("someone@example.com"),username: String::from("someusername123"),active: true,sign_in_count: 1,};println!("User 1: {} ({})", user1.username, user1.email);println!("Active: {}, Sign-in count: {}", user1.active, user1.sign_in_count);
}
代碼示例均通過 Rust 1.78 編譯測試。深入實踐可參考 The Rust Book 。