【Rust 基础入门】(04) | Rust 所有权

  • 0xE
  • 更新于 3天前
  • 阅读 357

Rust 通过所有权机制管理栈内存和堆内存,确保内存安全,避免数据竞争,并通过所有权转移控制变量的生命周期。

1. 栈内存与堆内存

Rust 中的内存管理主要涉及栈内存堆内存,这两种内存的使用方式不同,适用于不同的场景。

  • 栈内存:存储大小固定的数据,分配和释放速度非常快。栈内存遵循“后进先出”的原则,就像叠盘子一样,放盘子和取盘子都只能从顶部进行。

    • 例子:基础类型(如 i32charf64)存储在栈内存中。
  • 堆内存:存储大小动态变化的数据,分配和释放速度较慢,但更灵活。堆内存的使用方式类似于仓库,需要先找到一块足够大的空间,然后返回一个指向该空间的指针。

    • 例子:动态字符串(String 类型)存储在堆内存中。

2. 动态字符串与内存管理

Rust 中的 String 类型是一个动态字符串,它允许在运行时动态管理堆内存中的数据,比如分配、增长和修改字符串内容。

  • 创建动态字符串

    let s1 = String::from("hello"); // 在堆内存中分配空间存储 "hello"

    此时,s1 在栈内存中存储了堆内存的指针、字符串长度和容量信息。

  • 克隆(深拷贝): 如果需要对字符串进行修改而不影响原字符串,可以使用 clone 方法进行深拷贝:

    let s3 = s1.clone(); // 在堆内存中复制一份数据,s3 指向新的内存空间
    println!("s1 = {}, s3 = {}", s1, s3); // s1 和 s3 是两个独立的数据

    克隆操作会复制堆内存中的数据,因此对性能有一定影响,尤其是处理大数据或频繁操作时。

3. 所有权机制

Rust 的所有权机制是其内存安全的核心,确保程序在运行时不发生数据竞争、悬垂指针等内存安全问题。

  • 所有权三原则

    1. 每个值都有一个所有者(变量)。
    2. 一个值同时只能有一个所有者。
    3. 当所有者离开作用域时,值会被自动释放(drop)。
  • 所有权转移(Move): 当值被赋值给另一个变量时,所有权会转移,原变量将无法再使用该值。

    let s1 = String::from("hello");
    let s2 = s1; // 所有权从 s1 转移到 s2
    // println!("{}", s1); // 错误:s1 不再拥有数据
    println!("{}", s2); // 正确:s2 拥有数据
  • 作用域与内存释放: 变量的有效范围从声明的地方开始,直到当前作用域结束。当变量离开作用域时,其占用的内存会被自动释放。

    {
      let s1 = String::from("hello"); // s1 进入作用域
    } // s1 离开作用域,内存被释放

4. 浅拷贝与所有权转移

在其他语言(如 Java)中,浅拷贝只复制栈内存中的指针,多个变量共享同一块堆内存数据。这种方式效率高,但容易引发数据竞争问题。

Rust 通过所有权机制避免了浅拷贝带来的问题:

  • 所有权转移时,只进行“浅拷贝”(复制栈内存中的指针信息),但原变量会失去所有权。
  • 新变量接管所有权后,原变量失效,确保每个值只有一个清晰定义的所有者。

5. 总结

  • 栈内存用于存储固定大小的数据,速度快。
  • 堆内存用于存储动态大小的数据,灵活性高。
  • 所有权机制确保内存安全,避免数据竞争。
  • 所有权转移涉及浅拷贝和原变量失效,确保每个值只有一个所有者。
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
0xE
0xE
0x59f6...a17e
17年进入币圈,Web3 开发者。刨根问底探链上真相,品味坎坷悟 Web3 人生。工作机会可加v:__0xE__