Skip to content

结构体基础

> 理解结构体如何组织相关数据,掌握结构体定义、创建实例和字段访问的基本语法。

为什么需要结构体?

结构体语法

概念名称: 结构体将相关数据组织在一起,字段有名字。

语法结构:
┌──────────────────────────────────────┐
│  struct 结构体名 {                    │
│      字段1: 类型1,                    │
│      字段2: 类型2,                    │
│  }                                    │
│                                       │
│  let 实例 = 结构体名 {                │
│      字段1: 值1,                      │
│      字段2: 值2,                      │
│  };                                   │
│                                       │
│  访问:实例.字段名                     │
└──────────────────────────────────────┘

最简示例

rust
struct User {
    username: String,
    active: bool,
}

fn main() {
    let user = User {
        username: String::from("alice"),
        active: true,
    };
    println!("{}", user.username);
}
▶ Run

问题场景

rust
// 问题:描述一个人
// 使用多个独立变量(混乱)
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 吗?)
▶ Run

结构体的解决方案

rust
// 使用结构体(清晰)
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. 类型安全
▶ Run

结构体 vs 元组

┌─────────────────────────────────────────────────────┐
│           结构体 vs 元组                             │
├─────────────────────────────────────────────────────┤
│                                                     │
│  元组 (Tuple)                                       │
│  ├── 字段无名字(.0, .1, .2)                       │
│  ├── 适合临时组合                                   │
│  └── 例:(x, y) = 坐标                              │
│                                                     │
│  结构体 (Struct)                                    │
│  ├── 字段有名字(.name, .age)                      │
│  ├── 适合描述现实事物                               │
│  └── 例:Person { name, age, email }               │
│                                                     │
└─────────────────────────────────────────────────────┘

定义和创建结构体

基本语法

rust
// 步骤 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);
}
▶ Run

结构体内存布局

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
struct 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);
}
▶ Run

字段初始化简写

当变量名与字段名相同时

rust
struct 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);
}
▶ Run

函数返回结构体

rust
struct 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);
}
▶ Run

小结

  • 结构体将相关数据组织在一起,字段有名字(比元组更清晰)
  • struct Name { field: Type } 定义,Name { field: value } 创建
  • let mut 使整个实例可变,不支持单个字段可变
  • 字段初始化简写:当变量名与字段名相同时可省略

练习题

详见:练习题