Rust - 结构体
Rust - 结构体(Structs)
Section titled “Rust - 结构体(Structs)”虽然数组和向量非常适合存储相同类型的列表,但大多数真实世界的数据更为复杂。结构体(structure),或简称 struct,是一种自定义数据类型,允许你将构成有意义实体的多个相关值组合并命名。这些值,称为字段(fields),可以是不同的类型。
结构体是为应用程序域建模的基本构建块。例如,你可以创建一个 User 结构体来将用户名、电子邮件和活动状态都存储在一个地方。
声明和实例化结构体
Section titled “声明和实例化结构体”你使用 struct 关键字定义结构体,后跟其名称以及大括号内的字段及其类型。要使用结构体,你通过为每个字段指定具体值来创建其实例(instance)。
// Add this attribute to allow printing the struct for debugging.#[derive(Debug)]struct User { username: String, email: String, sign_in_count: u64, active: bool,}
fn main() { // Create an instance of the User struct. let user1 = User { email: String::from("contact@example.com"), username: String::from("exampleuser123"), active: true, sign_in_count: 1, };
// Access fields using dot notation. println!("Username: {}", user1.username);
// Print the entire struct using the debug formatter. println!("User details: {:?}", user1);}Username: exampleuser123User details: User { username: "exampleuser123", email: "contact@example.com", sign_in_count: 1, active: true }可变性与字段更新
Section titled “可变性与字段更新”要修改结构体的字段,整个实例必须用 mut 关键字标记为可变。Rust 不允许将单个字段标记为可变。
#[derive(Debug)]struct User { username: String, email: String, sign_in_count: u64, active: bool,}
fn main() { let mut user1 = User { email: String::from("contact@example.com"), username: String::from("exampleuser123"), active: true, sign_in_count: 1, };
println!("Original email: {}", user1.email);
// Modify a field on the mutable instance. user1.email = String::from("new.email@example.com");
println!("New email: {}", user1.email);}Original email: contact@example.comNew email: new.email@example.com结构体、函数与所有权
Section titled “结构体、函数与所有权”理解结构体如何与函数交互是理解 Rust 所有权系统(ownership system)的关键。你可以通过值(移动所有权)或通过引用(借用)将结构体传递给函数。
按值传递 (移动所有权)
Section titled “按值传递 (移动所有权)”如果你直接传递一个结构体,所有权就会被移动到函数中。原始变量将不能再被使用。
struct Article { title: String, author: String }
// This function takes ownership of the Article.fn process_article(article: Article) { println!("Processing article: '{}' by {}", article.title, article.author);}
fn main() { let my_article = Article { title: String::from("Understanding Ownership"), author: String::from("Rust Coder") };
process_article(my_article); // Ownership is moved here.
// The following line would cause a compile error because `my_article` has been moved. // println!("Title: {}", my_article.title);}按引用传递 (借用)
Section titled “按引用传递 (借用)”要允许函数使用结构体而不获取所有权,请传递它的引用(&)。对于只读访问,这几乎总是首选。
struct Article { title: String, author: String }
// This function borrows the Article immutably.fn display_article(article: &Article) { println!("Displaying article: '{}' by {}", article.title, article.author);}
fn main() { let my_article = Article { title: String::from("Understanding Borrows"), author: String::from("Rust Coder") };
display_article(&my_article); // We pass a reference.
// This is fine! `my_article` was only borrowed, not moved. println!("The article is still available: {}", my_article.title);}使用方法定义行为
Section titled “使用方法定义行为”方法是定义在结构体(或枚举、特性)上下文中的函数。它们使用 impl(实现)块声明。方法的第一个参数总是 self,它代表调用该方法的结构体实例。
#[derive(Debug)]struct Rectangle { width: u32, height: u32,}
// Implementation block for the Rectangle struct.impl Rectangle { // This is a method. `&self` is a shorthand for `self: &Self`. // It borrows the instance immutably. fn area(&self) -> u32 { self.width * self.height }
// Another method to check if a rectangle can hold another. fn can_hold(&self, other: &Rectangle) -> bool { self.width > other.width && self.height > other.height }}
fn main() { let rect1 = Rectangle { width: 30, height: 50 }; let rect2 = Rectangle { width: 10, height: 40 };
println!( "The area of the rectangle is {} square pixels.", rect1.area() // Call the method using dot notation. );
println!("Can rect1 hold rect2? {}", rect1.can_hold(&rect2));}The area of the rectangle is 1500 square pixels.Can rect1 hold rect2? true关联函数(静态方法)
Section titled “关联函数(静态方法)”在 impl 块中不将 self 作为参数的函数称为关联函数(associated functions)。它们与结构体类型本身相关联,而不是与特定实例关联。它们通常用作构造函数来创建结构体的新实例。构造函数的惯用名称是 new。
struct Point { x: f64, y: f64 }
impl Point { // An associated function, often used as a constructor. // It's called using the `::` syntax. fn new(x: f64, y: f64) -> Point { Point { x, y } // Field init shorthand syntax }
// Another associated function. fn origin() -> Point { Point { x: 0.0, y: 0.0 } }
// A method to display the point. fn display(&self) { println!("Point(x: {}, y: {})", self.x, self.y); }}
fn main() { // Call the `new` associated function. let p1 = Point::new(10.5, 20.2); p1.display();
// Call the `origin` associated function. let origin = Point::origin(); origin.display();}Point(x: 10.5, y: 20.2)Point(x: 0.0, y: 0.0)其他结构体变体
Section titled “其他结构体变体”Rust 还提供了另外两种结构体变体,适用于不同的用例:
- 元组结构体(Tuple Structs):当你想要给一个元组命名并使其成为一个独特的类型,但字段不需要名称时非常有用。例如:
struct Color(u8, u8, u8); - 单元结构体(Unit-Like Structs):没有任何字段的结构体。它们在泛型编程或当你需要为一个类型实现一个特性(trait)但没有数据要存储时非常有用。例如:
struct AlwaysEqual;