所有权

43 阅读1分钟
  • 每个值在某一时刻只能有一个所有者

  • 当所有者离开作用域,该值被释放(自动释放内存)

  • 如果将值赋给另一个变量,原变量将失效(除非是 Copy 类型)

字符串的所有权转移

fn main() {
    let s1 = String::from("hello");
    let s2 = s1;

    // println!("{}", s1); // ❌ 报错:s1 不再有效
    println!("{}", s2); // ✅ 有效
}
  • String 是堆分配类型

  • let s2 = s1; 实际发生的是**“所有权移动”(move)**

  • s1 变得“无效”,防止二次释放内存

类型分类

举例

存储位置

栈分配类型

i32, [u8; 4], struct 含栈字段

栈上

堆分配类型

Box<T>, Vec<T>, String, Rc<T>

堆上

特性

&'static str ("hehe")

String::from("haha")

类型

&str

String

所在内存

静态只读内存 + 栈

栈 + 堆

是否可变

否(除非重新绑定)

是(如果声明为 mut

拥有权

无,a 是借用

有,b 拥有堆上数据

适用场景

字面量、只读数据

动态字符串操作

函数参数也会转移所有权

fn main() {
    let s = String::from("hi");
    take_ownership(s);

    // println!("{}", s); // ❌ 报错,s 已被 move
}

fn take_ownership(str: String) {
    println!("I got: {}", str);
}

如何避免 move 之后无法访问

使用引用

fn main() {
    let s = String::from("hi");
    print_ref(&s);  // 传引用(借用),s 不会失效
    println!("s 仍然有效:{}", s);
}

fn print_ref(s: &String) {
    println!("{}", s);
}

函数返回所有权

fn main() {
    let s = String::from("hi");
    let s = take_and_return(s);
    println!("现在还能访问:{}", s);
}

fn take_and_return(str: String) -> String {
    println!("使用了:{}", str);
    str
}