-
每个值在某一时刻只能有一个所有者
-
当所有者离开作用域,该值被释放(自动释放内存)
-
如果将值赋给另一个变量,原变量将失效(除非是 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
}