Rust 中的所有权
Rust 通过一个所有权系统来管理内存,其中包含了一组编译器在编译时检查的规则,当程序运行时,所有权特性不会减慢程序的运行速度
栈(stack)和堆(heap)的概念
所有存在栈上的数据必须是在编译时就已经确定大小的数据,编译时大小未知或运行时大小可能发生改变的数据必须存放在堆上
栈上的数据在操作上比堆上的数据速度要快
所有权的规则
每个值都归属于一个变量,此变量是该值得所有者
每个值同时只能有一个所有者
当所有者超出作用域时,该值将被删除
变量的复制,移动和克隆
复制
如果一个类型实现了 copy trait,那么旧的变量在被赋值后仍然可用
如果一个类型或该类型的一部分实现了drop trait,那么rust就不允许它再实现copy trait
拥有copy trait的类型
任何简单标量及全部由简单标量构成的组合类型都可以是copy的,如:所有的整数/浮点/字符/由标量组成的元组等
任何需要分配内存或某种资源的都不是copy的
移动
未实现copy trait的类型如:String 类型,在被赋值给另一个变量的同时,会将所有权一并转交给新的变量,赋值后,当前变量将会失效
移动类似于变量的浅拷贝,但在浅拷贝的同时,使原有变量失效
示例一:通过
=
赋值
let s1 = String::from("Hello");
let s2 = s1;
// 下列语句报错, 赋值后 s1 将会失效, 不可被访问
println!("s1: {}", s1);
let a = 123;
let b = a;
// 下列语句合法, 队友标量类型, 自动实现了 copy trait
println!("a = {}", a);
示例二:通过函数传参
fn main() {
let s1 = String::from("Hello");
// 通过函数调用传参, s1 将所有权转移至函数内部, 同时 s1 将失效
// 但函数内部又将 s 进行了返回, 因此又将变量的所有权转交给了 s2
let s2 = say_hello(s1);
// 下述语句报错, 给函数传参后 s1 将会失效, 不可被访问
println!("s1: {}", s1);
}
fn say_hello(s: String) -> String {
println!("Say: {}", s);
s
}
克隆
通过clone可以在赋值时实现变量的深拷贝,clone后,原有变量依然有效
let s1 = String::from("Hello");
let s2 = s1.clone();
// 通过 clone 进行赋值, 原变量依然有效
println!("s1: {}", s1);
引用和借用
不可变引用:不能修改原变量的值
引用某些值但不取得其所有权,符号为:
&
fn main() {
let s1 = String::from("Hello");
// 通过引用将该值传递给函数, 但不转交所有权, 函数调用后, s1 仍然有效
say_hello(&s1);
// 下列语句合法, s1 仍然有效
println!("s1 = {}", s1);
}
fn say_hello(s: &String){
println!("Say: {}", s);
}
可变引用:可以修改原变量的值
在同一作用域,同时只能存在一个可变引用,且不能同时拥有可变引用和不可变引用,但可以同时拥有多个不可变的引用
fn main() {
let mut s1 = String::from("Hello");
say_hello(&mut s1);
// s1 的值已被函数修改
println!("s1 = {}", s1);
}
fn say_hello(s: &mut String){
s.push_str(", world!");
println!("Say: {}", s);
}
/* 输出:
Say: Hello, world!
s1 = Hello, world!
*/
借用
通过引用来给函数传递参数的这个行为被称为
借用
评论区