Rust所有权机制

编程入门 行业动态 更新时间:2024-10-24 01:56:25

Rust<a href=https://www.elefans.com/category/jswz/34/1740575.html style=所有权机制"/>

Rust所有权机制

前言

所有权机制是Rust的核心功能之一,对于初学者算是一个重难点,它保证了程序无需GC,即可自动化的释放内存
希望这篇博客可以帮助你快速理解所有权机制

概念

Rust的值都只有一个变量是该值的所有者
所有者可以切换,但是值在任一时刻有且仅有一个所有者
当所有者离开作用域,该值将被丢弃

错误示例

在变量的作用域之外访问该变量

fn main() {{let s = String::from("hello"); // 创建字符串,该字符串的所有者是变量s} // 离开作用域,该字符串被丢弃println!("{}", s); // 编译报错,此时变量s已被释放,无法访问变量s
}

访问一个所有权被转移的变量

fn main() {let s = String::from("hello"); // 创建字符串,该字符串的所有者是变量slet a = s; // 字符串的所有权从变量s传递给变量aprintln!("{}",s); // 编译报错,此时字符串的所有权已被转移,无法在通过变量s访问字符串
}

访问一个所有权被转移的变量

fn main() {let s = String::from("hello"); // 创建字符串,该字符串的所有者是变量stakes_ownership(s); // 字符串的所有权从变量s传递给函数takes_ownershipprintln!("{}",s); // 编译报错,此时字符串的所有权已被转移,无法在通过变量s访问字符串
}fn takes_ownership(s: String) {println!("我拿到了字符串\"{}\"的所有权", s); // 拿到字符串的所有权
} // 离开作用域,该字符串被丢弃

借用

在上述错误示例中,我们不难发现,如果我们把String字符串的所有权传递给函数,那么等到函数结束,我们就无法在使用该字符串了,对于我们,这显然是无法接受的,那么几种解决方法解决这个问题,例如

fn main() {let mut s = String::from("hello");s = takes_ownership(s);println!("{}", s);
}fn takes_ownership(s: String) -> String {println!("我拿到了字符串\"{}\"的所有权", s); // 拿到字符串的所有权s // 返回该字符串
}
fn main() {let mut s = String::from("hello");s = takes_ownership(s);println!("{}", s);
}fn takes_ownership(s: String) -> String {println!("我拿到了字符串\"{}\"的所有权", s); // 拿到字符串的所有权s // 返回该字符串
}

但是上述做法并不优雅,Rust推荐的做法是我们通过借用来解决这个问题,借用就是创建一个引用的行为,例如

fn main() {let s = String::from("hello");takes_ownership(&s); // 将字符串的引用传递给函数println!("{}", s);
}fn takes_ownership(s: &String) { // 借用到字符串的引用println!("我借用到了字符串\"{}\"的引用", s);
} // 此时字符串的所有权并没传递给函数,应此该函数没有资格释放该字符串

如果我们需要在函数内部修改字符串,那么我们可以借用字符串的可变引用

fn main() {let mut s = String::from("hello");takes_ownership(&mut s); // 将字符串的引用传递给函数println!("{}", s);
}fn takes_ownership(s: &mut String) { // 借用到字符串的可变引用println!("我借用到了字符串\"{}\"的可变引用", s);s.push_str(" world"); // 修改该字符串
} // 此时字符串的所有权并没传递给函数,应此该函数没有资格释放该字符串

可变引用虽好,但是有个注意事项,就是同一时刻可变引用只能有一个,当存在可变引用的时候,就不能有不可变引用,但是当可变引用不存在的时候,就可以存在数个不可变引用,例如

fn main() {let mut s = String::from("hello");let (a, b) = (&s, &s); // 借用两个字符串的不可变引用println!("不可变借用a:{}, 不可变借用b:{}", a, b);let c = &mut s; // 借用字符串的可变引用,此时前面的两个不可变引用不再生效c.push_str(" world");println!("{}", c);
}

还有一个注意事项就是,引用的内容必须合法,例如下面的错误示范

fn main() {let s = dangle();
}fn dangle() -> &String {let s = String::from("hello"); // 创建字符串,该字符串的所有者是变量s&s // 返回字符串的引用,但是此时字符串要已经离开作用域被释放了,因此当函数结束,这个引用将是一个非法的悬垂引用,不过还好,在rust中这种行为无法通过编译
}

总结一下引用的规则

  1. 在任意时刻只能有一个可变引用,要么只能有多个不可变引用
  2. 引用必须有效

更多推荐

Rust所有权机制

本文发布于:2023-12-06 09:54:44,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1667216.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:所有权   机制   Rust

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!