Rust 的所有权

Rust 中的所有权

为了兼顾内存使用的安全性能,Rust 在设计之初就采用了与 C++ 完全不同的内存管理。

Rust 引入了**所有权(ownership)**的概念:

  • Rust 中的每个值都有所有者 (owner)。
  • 同一时刻每个值只有一个所有者。
  • 当所有者失效,值也将被丢弃。

变量绑定

变量通过绑定的方式,获得对数据的所有权。如果一个绑定超出作用域,其绑定的数据将被自动释放。

let a = 1;

变量之间的赋值行为,将会直接导致绑定关系的变化,这一语义被称为移动所有权,亦即掩盖 (shadowing)

let s1 = String::from("hello");
let s2 = s1; // 字符串 "hello" 已经被 s2 绑定,s1 悬置。

println!("{s1}, world!");
// 此时将发生编译错误 error: borrow of moved value: `s1`

借用

但并非所有语境下的变量赋值都希望移交所有权,这个时候应该采用 Rust 中的**借用(borrow)**概念。

借用规则

let v = vec![1, 2, 3];
let v_ref = &v; // v_ref is a reference to v.

可变借用与不可变借用

Rust 类型系统中,变量被分为可变不可变。在借用中,同理可分为可变借用 &mut不可变借用 &

fn main() {
    let mut vector: Vec<i32> = vec![];
    let vector_ref: &mut Vec<i32> = &mut vector; 
    push(vector_ref, 4);
}

函数参数中的借用

需要注意的是,函数参数传递时,采用的是与变量赋值和借用相同的语法规则。如果不指定 &&mut,变量会直接发生移动。

fn hello_move(s: String) {
    println!("Message by moving: {}", S);
}

fn hello_borrow(s: &String) {
    println!("Message by borrowing: {}", S);
}

fn main() {
    let x: String  = String::from("hello");
    let y: String  = String::from("hello");
    
    hello_move(x);
    hello_borrow(&y);
    
    println!("x:{}",x); // error[E0382]: borrow of moved value: `x`
    println!("y:{}",y); // This runs normally. 
}

所有权的思想贯穿了 Rust 编程的全过程,在后续的 变量函数结构体 等章节中,你还会多次遇到所有权的转移借用问题。