悬垂指针
// p1和p2指向同一个内存地址
char *p1 = new string("");
char *p2 = p1;
// 在操作p2的时候,可能会将该内存删除(比如追加字符串的实现可能是这样的:)
function string::push_str(string str) {
string new_str = new string(this.chars() + str);
delete this; // 擅自释放旧内存
return new_str;
}
p2.push_str(""); // 该调用导致内存被释放,可能被清零,可能被其它变量复用
// p1成为了悬垂指针!!!
什么是所有权
为了避免出现悬垂指针,Rust引入了所有权概念。
char *p1 = new string("");
char *p2 = p1; // 内存的所有权被转移给p2
p1.push_str(""); X! p1不再具有内存的所有权,push_str()函数要求所有权才有内存的生杀大权,编译失败
所有权避免重复释放内存
fn main() -> std::io::Result<()> {
let a = Box::new(8);
if true {
let b = a;
println!("{}", b);
// b的生命周期结束,内存被释放
}
println!("{}", a); X! a没有所有权,无法使用,编译失败
Ok(())
}
要避免内存被释放(在确定不需要释放内存的情况下),就属于借用内存:
fn main() -> std::io::Result<()> {
let a: Box<i32> = Box::new(8);
if true {
let b: &Box<i32> = &a; // 向a借用一下内存,不会删除你的东西,放心好啦!(也不会修改的,如果修改的话我会说&mut a)
println!("{}", b);
// 由于b的类型是引用,说明内存的所有权被其它变量拥有,因此不会释放堆内存。
}
println!("{}", a);
Ok(())
}