Rust 定义与实例化结构体
文章目录
- 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 。