结构体基础
> 理解结构体如何组织相关数据,掌握结构体定义、创建实例和字段访问的基本语法。
为什么需要结构体?
结构体语法
概念名称: 结构体将相关数据组织在一起,字段有名字。
语法结构:
┌──────────────────────────────────────┐
│ struct 结构体名 { │
│ 字段1: 类型1, │
│ 字段2: 类型2, │
│ } │
│ │
│ let 实例 = 结构体名 { │
│ 字段1: 值1, │
│ 字段2: 值2, │
│ }; │
│ │
│ 访问:实例.字段名 │
└──────────────────────────────────────┘最简示例
rust
▶ Runstruct User {
username: String,
active: bool,
}
fn main() {
let user = User {
username: String::from("alice"),
active: true,
};
println!("{}", user.username);
}问题场景
rust
▶ Run// 问题:描述一个人
// 使用多个独立变量(混乱)
let name1 = String::from("Alice");
let age1 = 25;
let email1 = String::from("alice@example.com");
let name2 = String::from("Bob");
let age2 = 30;
let email2 = String::from("bob@example.com");
// 问题:
// 1. 数据分散,不直观
// 2. 难以传递给函数
// 3. 容易搞混(name1 对应 age1 吗?)结构体的解决方案
rust
▶ Run// 使用结构体(清晰)
struct Person {
name: String,
age: u32,
email: String,
}
let person1 = Person {
name: String::from("Alice"),
age: 25,
email: String::from("alice@example.com"),
};
let person2 = Person {
name: String::from("Bob"),
age: 30,
email: String::from("bob@example.com"),
};
// 优势:
// 1. 数据组织在一起,语义清晰
// 2. 容易传递和使用
// 3. 类型安全结构体 vs 元组
┌─────────────────────────────────────────────────────┐
│ 结构体 vs 元组 │
├─────────────────────────────────────────────────────┤
│ │
│ 元组 (Tuple) │
│ ├── 字段无名字(.0, .1, .2) │
│ ├── 适合临时组合 │
│ └── 例:(x, y) = 坐标 │
│ │
│ 结构体 (Struct) │
│ ├── 字段有名字(.name, .age) │
│ ├── 适合描述现实事物 │
│ └── 例:Person { name, age, email } │
│ │
└─────────────────────────────────────────────────────┘定义和创建结构体
基本语法
rust
▶ Run// 步骤 1:定义结构体
struct User {
active: bool, // 字段名:类型
username: String,
email: String,
sign_in_count: u64,
}
// 步骤 2:创建实例
fn main() {
let user1 = User {
active: true,
username: String::from("alice"),
email: String::from("alice@example.com"),
sign_in_count: 1,
};
// 访问字段
println!("用户名:{}", user1.username);
println!("邮箱:{}", user1.email);
}结构体内存布局
struct User {
active: bool, // 1 字节
username: String, // 24 字节(指针 + 长度 + 容量)
email: String, // 24 字节
sign_in_count: u64, // 8 字节
}
内存布局(简化):
┌─────────┬──────────────┬──────────────┬─────────┐
│ active │ username │ email │ count │
│ 1 byte │ 24 bytes │ 24 bytes │ 8 bytes │
└─────────┴──────────────┴──────────────┴─────────┘
实际大小:约 57-64 字节(考虑内存对齐)可变结构体
rust
▶ Runstruct User {
active: bool,
username: String,
}
fn main() {
// 不可变实例
let user1 = User {
active: true,
username: String::from("alice"),
};
// user1.username = String::from("bob"); // ❌ 错误
// 可变实例
let mut user2 = User {
active: true,
username: String::from("alice"),
};
user2.username = String::from("bob"); // ✅ 正确
user2.active = false; // ✅ 正确
println!("用户名:{}", user2.username);
}字段初始化简写
当变量名与字段名相同时
rust
▶ Runstruct User {
username: String,
email: String,
active: bool,
}
fn main() {
// 传统写法(冗余)
let username = String::from("alice");
let email = String::from("alice@example.com");
let user1 = User {
username: username, // 重复
email: email, // 重复
active: true,
};
// 简写写法(推荐)
let username = String::from("bob");
let email = String::from("bob@example.com");
let user2 = User {
username, // 等同于 username: username
email, // 等同于 email: email
active: true,
};
println!("user1: {}, user2: {}", user1.username, user2.username);
}函数返回结构体
rust
▶ Runstruct User {
username: String,
email: String,
active: bool,
sign_in_count: u64,
}
// 使用简写
fn build_user(email: String, username: String) -> User {
User {
email, // 等同于 email: email
username, // 等同于 username: username
active: true,
sign_in_count: 1,
}
}
fn main() {
let user = build_user(
String::from("test@example.com"),
String::from("testuser")
);
println!("用户:{} ({})", user.username, user.email);
}小结
- 结构体将相关数据组织在一起,字段有名字(比元组更清晰)
struct Name { field: Type }定义,Name { field: value }创建let mut使整个实例可变,不支持单个字段可变- 字段初始化简写:当变量名与字段名相同时可省略
练习题
详见:练习题