Rust语言内存管理之妙

首发于我的rust 学习日记

规则

  • Rust 中的每一个值都有一个被称为其 所有者(owner)的变量。
  • 值有且只有一个所有者。
  • 当所有者(变量)离开作用域,这个值将被丢弃。(Rust 在结尾的 }处自动调用 drop释放内存)
  • 移动(堆内存变量),当值(s1)被赋值给另外一个变量(s2)后,rust则认为变量s1,不再有效。
  • 栈类型变量无移动的说法(没有深浅拷贝的区别)
  • 将值传递给函数在语义上与给变量赋值相似

变量与数据的交互(move)

  • 将 5 绑定到 x;接着生成一个值 x 的拷贝并绑定到 y。现在有了两个变量,x 和 y,都等于 5。因为正数是有已知固定大小的简单值,所以这两个 5 被放入了栈中(重点:两个值都放入栈中了)。
    let x = 5;
    let y = x;
    复制代码
  • s1 和 s2 这两个变量指向相同的地址(hello分配的堆内存)。
    let s1 = String::from("hello");
    let s2 = s1;
    复制代码
  • 图1-1(s1 的内存引用图)

  • 图1-2(s1和s2的引用图(错误)其他语言js\go 是这样的)

  • 图1-3(s1和s2的引用图(正确)rust 是这样的,s1赋值s2后,Rust 则认为 s1 不再有效)

当值(s1)被赋值给另外一个变量(s2)后,rust则认为变量s1,不再有效(图1-3)

  • Rust 在结尾的 }(作用域结束后) 处自动调用 drop(释放内存)。
  • 如上图,当 s2 和 s1 离开作用域,他们都会尝试释放相同的内存。这是一个叫做 二次释放(是错误的)。
  • 为了确保内存安全,Rust 则认为 s1 不再有效,因此 Rust 不需要在 s1 离开作用域后清理任何东西,如下案例。
    fn main() {
        let s1 = String::from("hello");
        let s2 = s1;
    
        // 本行会报错 value borrowed here after move
        println!("{}, world!", s1);
    }
    复制代码

克隆(深拷贝)

  • 实现如下图,赋值变量的同时,进行数据拷贝的方案,rust也是支持的
  • 这段代码能正常运行,产生的变量内存如图1-4
    fn main() {
        let s1 = String::from("hello");
        let s2 = s1.clone();
    
        println!("s1 = {}, s2 = {}", s1, s2);
    } 
    复制代码
  • 图1-4

栈类型变量无移动的说法(纯拷贝)

  • x,y是编译时确定大小的类型,因此整个存储在栈上,所以拷贝其实际的值是快速的。因此rust对栈变量进行纯拷贝,便不会造成性能的影响。
  • 也就意味着创建变量 y 后, 没必要使x 无效。
let x = 5;
let y = x;

println!("x = {}, y = {}", x, y);
// x = 5, y = 5
复制代码

将值传递给函数在语义上与给变量赋值相似

fn main() {
    let s = String::from("hello");  // s 进入作用域

    run_move(s);                    // s 的值移动到函数里,s失效
                                    // 因此到这里,s不再有效
    /* 
    将会报错:因为s已经被move
    报错信息:will error value borrowed here after move
    println!("s:{}",s);            
    */
    let x = 5;                      // x 进入作用域

    run_copy(x);                    // x 应该移动函数里
    println!("x:{}",x);             // 因为 x 是 栈变量,因为不会被 move 使失效

} 
//  x 移出了作用域,
//  s 移出了作用域但,因为 s 的值已被移走,所以不会有特殊操作

fn run_move(some_string: String) { // some_string 进入作用域
    println!("run_move:{}", some_string);
} // 这里,some_string 移出作用域并调用 `drop` 方法。占用的内存被释放

fn run_copy(some_integer: i32) { // some_integer 进入作用域
    println!("run_copy:{}", some_integer);
} // some_integer 移出作用域
复制代码
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Rust内存管理优势主要体现在以下几个方面: 1. 零成本抽象:Rust提供了诸多高级抽象特性,如所有权系统、借用检查器和生命周期等,但这些抽象在运行时几乎没有额外的开销。这意味着Rust可以在保证安全性的同时,避免了传统垃圾回收机制引入的运行时开销。 2. 所有权系统:Rust的核心特性之一就是所有权系统。通过所有权系统,Rust确保每块内存只有一个所有者,并且在编译时进行静态检查,避免了数据竞争和内存错误。这使得Rust能够在编译时捕获内存安全问题,而不需要运行时的垃圾回收或引用计数。 3. 借用检查器:Rust的借用检查器确保了对数据的访问是安全和有效的。它通过引入借用规则和生命周期来确保内存的正确使用。借用检查器在编译时检查借用关系,并防止数据竞争和悬垂指针等常见错误。 4. 内存安全性:Rust在编译时保证了内存安全性,避免了常见的内存错误,如空指针引用、野指针访问和缓冲区溢出等。这使得Rust能够提供更高的代码可靠性和稳定性,减少了潜在的安全漏洞。 总体而言,Rust内存管理优势在于其强大而高效的所有权系统和借用检查器,能够在编译时捕获内存错误,并保证内存安全性,同时避免了传统垃圾回收机制引入的运行时开销。这使得Rust成为一种适用于系统级编程和高性能应用的语言选择。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值