侧边栏壁纸
博主头像
喵记博主等级

行动起来,活在当下

  • 累计撰写 18 篇文章
  • 累计创建 4 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Rust(五):所有权

张秋平
2024-02-12 / 0 评论 / 0 点赞 / 3 阅读 / 3683 字

Rust 中的所有权

Rust 通过一个所有权系统来管理内存,其中包含了一组编译器在编译时检查的规则,当程序运行时,所有权特性不会减慢程序的运行速度

栈(stack)和堆(heap)的概念

  • 所有存在栈上的数据必须是在编译时就已经确定大小的数据,编译时大小未知或运行时大小可能发生改变的数据必须存放在堆上

  • 栈上的数据在操作上比堆上的数据速度要快

所有权的规则

  1. 每个值都归属于一个变量,此变量是该值得所有者

  2. 每个值同时只能有一个所有者

  3. 当所有者超出作用域时,该值将被删除

变量的复制,移动和克隆

复制

  • 如果一个类型实现了 copy trait,那么旧的变量在被赋值后仍然可用

  • 如果一个类型或该类型的一部分实现了drop trait,那么rust就不允许它再实现copy trait

拥有copy trait的类型

  1. 任何简单标量及全部由简单标量构成的组合类型都可以是copy的,如:所有的整数/浮点/字符/由标量组成的元组等

  2. 任何需要分配内存或某种资源的都不是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!
*/

借用

  • 通过引用来给函数传递参数的这个行为被称为借用

0

评论区