Rust 结构体 (struct) 的详细知识点

 更新时间:2026年06月24日 08:23:46   作者:菜鸟谢  
本文主要介绍了Rust结构体(struct)的详细知识点,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

涵盖:三类形式、实例化语法、内存布局、方法 impl、派生 trait、递归结构体等
特点:结合栈/堆分配详解,含高频易错点总结

一、结构体三类形式

Rust 有三种结构体,用途完全不同:

1. 具名字段结构体(最常用)

每个成员带字段名,适合复杂业务数据:

struct User {
    name: String,
    age: u32,
    is_vip: bool,
}

// 实例化
let u = User {
    name: "张三".to_string(),
    age: 22,
    is_vip: false,
};

// 访问/修改(必须 mut 实例)
println!("{}", u.name);
let mut u2 = User { name: "李四".into(), age: 30, is_vip: true };
u2.age = 31;

2. 元组结构体(无字段名,只用下标访问)

适合简单包装、FFI、newtype 模式:

struct Point(i32, i32);
struct Color(u8, u8, u8);

let p = Point(10, 20);
println!("{} {}", p.0, p.1);

3. 单元结构体(无任何字段)

仅用作标记、trait 实现标记类型:

struct EmptyFlag;
let flag = EmptyFlag;

二、实例化简写语法

1. 字段简写(变量名和字段同名)

fn build_user(name: String, age: u32) -> User {
    User {
        name,  // 等价 name: name
        age,
        is_vip: false,
    }
}

2. 结构体更新语法..复用旧实例

只修改部分字段,其余继承原有值:

let u1 = User { name: "A".into(), age: 18, is_vip: false };
let u2 = User { age: 20, ..u1 };
// u2.name = "A", u2.is_vip = false,仅 age 改为 20

⚠️ 所有权注意:..u1 会转移 u1 内堆类型字段所有权(String/Vec),之后不能再使用 u1。

三、内存布局 & 栈/堆分配(重点)

1. 纯值结构体(无任何堆类型字段)

所有成员都是 i32/f64/bool/[T;N] 等值类型:整个结构体完整平铺在栈,内部无指针,无堆内存。

struct Point { x: i32, y: f64 }
let p = Point {x:1, y:2.0}; // 全部栈

2. 结构体包含堆容器字段(String/Vec/Box/Arc 等)

结构体实例本体依然在;只是对应字段内部存储指针,真实数据存堆。

struct Student {
    id: u64,
    name: String,   // String 栈存三元指针,字符堆
    scores: Vec<u8> // Vec 栈存指针数组,元素堆
}
let s = Student { ... };
// s 整体在栈;name、scores 的真实数据在堆

3. 结构体整体放到堆上

外层套 Box/Rc/Arc/Mutex,栈只存一根指针,结构体本体全部堆分配:

let heap_point: Box<Point> = Box::new(Point{x:0, y:0});
// heap_point 变量栈;Point 结构体存在堆

4. 内存对齐与布局

情况说明
默认Rust 不保证字段顺序、对齐和 C 一致,编译器会重排优化内存
#[repr(C)]如需和 C 交互固定布局,加此属性
#[repr(C)]
struct CPoint {
    x: i32,
    y: i32,
}

四、结构体方法 impl

1. 关联函数(无 &self,类似构造器)

调用方式:Type::func(),常命名为 new()

impl User {
    // 构造器,关联函数
    fn new(name: &str, age: u32) -> Self {
        Self {
            name: name.to_string(),
            age,
            is_vip: false,
        }
    }
}
let u = User::new("老王", 25);

2. 实例方法(带 &self / &mut self / self)

参数类型含义
&self只读借用,不修改结构体
&mut self可变借用,修改内部字段
self获取所有权,调用后原实例失效
impl User {
    // 只读方法
    fn get_age(&self) -> u32 {
        self.age
    }
    // 修改自身
    fn become_vip(&mut self) {
        self.is_vip = true;
    }
    // 拿走所有权
    fn consume(self) {
        println!("{}", self.name);
    }
}

3. 关联常量

impl User {
    const MAX_AGE: u32 = 150;
}
println!("{}", User::MAX_AGE);

五、所有权与解构

1. 解构赋值

let User { name, age, is_vip } = u;
// name 拿到 String 所有权,u 失效

只想借用不转移所有权:解构引用

let User { ref name, .. } = &u;
// 等价 let name = &u.name;

2. 字段借用规则

let mut u = User::new("test", 20);
let a = &u.name; // 不可变借用
let b = &mut u.age; // 可变借用
// 同一字段不能同时存在可变 + 不可变借用;不同字段允许

六、派生 trait(derive 常用)

给结构体自动实现标准功能,开发高频:

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Point { x: i32, y: i32 }
Trait功能
Debug支持 println!("{:?}", p) 打印调试信息
Clone.clone() 深拷贝实例
Copy值可栈拷贝,要求所有字段都实现 Copy(不能含 String/Vec)
PartialEq / Eq支持 == 相等比较
Hash可作为 HashMap key
DefaultUser::default() 快速生成默认值

Copy 关键限制:包含 String、Vec、Box 堆类型的结构体无法 derive Copy,只能 Clone。

七、嵌套结构体

结构体字段可以是另一个结构体:

struct Address {
    city: String,
    street: String,
}

struct User {
    name: String,
    addr: Address, // 嵌套结构体
}

// 访问
user.addr.city

八、递归结构体(自身包含自己)

直接嵌套会无限尺寸编译报错,必须用 Box 把自身放堆:

// 报错:无限大小
struct Node {
    next: Node
}

// 正确,Box 栈存指针,子节点堆分配
struct Node {
    val: i32,
    next: Option<Box<Node>>
}

九、结构体 vs 元组 vs 枚举 核心区分

类型特点
struct同时拥有所有字段,描述单一事物完整属性;可命名字段可读性强
tuple固定长度、可多类型、无字段名,轻量临时组合
enum同一时间仅存一种变体,互斥多种形态

十、高频易错点总结

⚠️ 以下易错点需特别注意

  1. 修改字段必须实例声明 mut,只标记字段 mut 无效
  2. 结构体更新语法 ..s 会转移堆字段所有权,原变量失效
  3. 含 String/Vec 的结构体不能 derive Copy,只能 Clone
  4. 递归结构体内部自引用必须包 Box,否则编译无限尺寸
  5. 无 #[repr(C)] 时内存字段顺序不固定,不能直接和 C 结构体对等
  6. 结构体本体默认栈分配;仅外层套 Box/Arc 时整体进堆
  7. 解构堆类型结构体默认转移所有权,想要借用需要匹配引用 &self

十一、速记口诀

结构三分具名元组单元,new 构造 impl 加方法;
点号访问可 mut 修改,..语法快速复用旧实例;
纯值字段全存栈,字符串 vec 堆上藏;
递归嵌套包 Box,derive 派生 Debug 克隆相等;
C 交互加 repr(C),Copy 仅限纯栈值类型。

到此这篇关于Rust 结构体 (struct) 的详细知识点的文章就介绍到这了,更多相关Rust 结构体内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • rust中间件actix_web在项目中的使用实战

    rust中间件actix_web在项目中的使用实战

    这篇文章主要介绍了rust中间件在项目中的使用实战,包括自定义中间件,日志中间件,Default headers,用户会话,错误处理的用法实例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2024-01-01
  • Rust中FFI编程知识点整理总结(推荐)

    Rust中FFI编程知识点整理总结(推荐)

    这篇文章主要介绍了Rust中FFI编程知识点整理总结,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-09-09
  • 用rust 写一个jar包 class冲突检测工具

    用rust 写一个jar包 class冲突检测工具

    这篇文章主要介绍了用rust 写一个jar包 class冲突检测工具 的相关资料,需要的朋友可以参考下
    2023-05-05
  • Rust版本号的使用方法详解

    Rust版本号的使用方法详解

    在 Rust 项目中,版本号的使用遵循语义版本控制(Semantic Versioning)原则,确保版本号的变化能准确反映代码的变更情况,本文给大家详细解释了Rust版本号用法,需要的朋友可以参考下
    2024-01-01
  • Rust中的宏之声明宏和过程宏详解

    Rust中的宏之声明宏和过程宏详解

    Rust中的宏是一种强大的工具,可以帮助开发人员编写可重用、高效和灵活的代码,这篇文章主要介绍了Rust中的宏:声明宏和过程宏,需要的朋友可以参考下
    2023-04-04
  • Rust中字符串类型String的46种常用方法分享

    Rust中字符串类型String的46种常用方法分享

    Rust主要有两种类型的字符串:&str和String,本文主要为大家介绍的是String类型的字符串以及它常用的46种方法,感兴趣的小伙伴可以了解一下
    2023-06-06
  • Rust 中的文件操作示例详解

    Rust 中的文件操作示例详解

    Rust 中的路径操作是跨平台的,std::path 模块提供的了两个用于描述路径的类型,本文给大家介绍Rust 中的文件操作示例详解,感兴趣的朋友一起看看吧
    2021-11-11
  • Rust 实现 async/await的详细代码

    Rust 实现 async/await的详细代码

    异步编程在 Rust 中的地位非常高,很多 crate 尤其是多IO操作的都使用了 async/await,这篇文章主要介绍了Rust 如何实现 async/await,需要的朋友可以参考下
    2022-09-09
  • rust 如何使用 cargo-nextest 替代 cargo test

    rust 如何使用 cargo-nextest 替代 cargo te

    cargo-nextest 是新一代的rust测试程序,能够极大提升测试性能,可以完全替代 cargo test 命令,这篇文章主要介绍了rust 如何使用 cargo-nextest 替代 cargo test,需要的朋友可以参考下
    2024-05-05
  • Rust 中单线程 Web 服务器的实现

    Rust 中单线程 Web 服务器的实现

    本文用Rust构建单线程Web服务器,通过HTTP/TCP处理请求,返回hello.html或404.html,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-06-06

最新评论