• 学习 Rust 的第七天:如何理解引用


    大家好,

    今天是我学 Rust 的第7天,今天我要来看一下引用和借用。昨天我学习了 Rust 的所有权模型,如果你对 Rust 一无所知的话,那篇文章是必读的。

    引用

    昨天我们看到,将参数传递给函数与将值赋给另一个变量产生了相同的效果,实际上导致了所有权的丧失。不过,有一个解决方法。
    如果你了解 C 语言,指针 是 C 语言的一个重要概念。而引用与之类似。

    让我们看一下代码并理解它:

    fn main(){  
      let s1: String = String::from("Hello World");  
      let length: usize = calculate_length(&s1); // & 用于传递字符串的引用  
      println!("`{}` 的长度为 {}" ,s1,length);  
    }  
      
    fn calculate_length(s: &String) -> usize {  
      s.len()  
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    Rust 中的引用是指针,允许借用和访问数据而不转移所有权,有助于内存安全,防止数据竞争。

    解释:

    • fn main(): 程序的入口点。
    • let s1: String = String::from("Hello World");: 声明一个 String 变量 s1,值为 “Hello World”。
    • let length: usize = calculate_length(&s1);: 调用 calculate_length 函数,传递对字符串 s1 的引用。
    • fn calculate_length(s: &String) -> usize: 函数以对 String 的引用 (&String) 作为参数,并返回它的长度作为 usize 类型。
    • s.len(): 获取引用 s 所指向的 String 的长度。
    • println!("{} 的长度为 {}" ,s1, length);: 打印原始字符串 s1 及其长度。

    关键概念:

    • & 用于传递对字符串的引用 (&s1),而不是转移所有权,防止字符串被移动或克隆。
    • 这种借用允许 calculate_length 函数在不获取所有权的情况下操作字符串。
    • 引用默认为不可变。

    感谢 Let's Get Rusty 在他的 YouTube 频道上提供这么棒的解释。

    可变引用

    我们上面看到的是不可变引用,我们无法真正改变值,但我们可以从中读取。让我们来看看 可变引用

    fn main() {  
        let mut s1 = String::from("Hello");  
      
        // 传递可变引用给 modify_string 函数  
        modify_string(&mut s1);  
      
        // 原始字符串现在被修改了  
        println!("修改后的字符串: {}", s1);  
    }  
      
    fn modify_string(s: &mut String) {  
        s.push_str(", World!"); // 通过追加来修改字符串  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    解释:

    • fn main(): 程序的入口点。
    • let mut s1 = String::from("Hello");: 声明一个可变的 String 变量 s1
    • modify_string(&mut s1);: 调用 modify_string 函数,传递对 s1 的可变引用。
    • fn modify_string(s: &mut String): 函数以对 String 的可变引用 (&mut String) 作为参数。
    • s.push_str(", World!");: 通过追加将 “, World!” 添加到 s 所指向的字符串。
    • println!("修改后的字符串: {}", s1);: 打印修改后的字符串。

    关键概念:

    • 可变引用可以通过 &mut 变量名 进行传递。

    可变引用的规则

    • 对于特定数据片段,只允许一个可变引用或多个不可变引用。
    • 在可变引用有效时,不允许对相同数据进行其他引用。
    • 可变引用受其作用域的约束,防止悬空引用。
    • 在特定作用域内只能存在一个可变引用,以确保协调的修改。

    简单来说,一个特定作用域内只能存在一个对变量的可变引用。

    虽然不可变引用的数量可以是无限的。

    但是,不可变和可变引用可以同时存在于相同的作用域内。

    示例:

    fn main(){  
      let mut string1: String = String::from("Hello World");  
      
      let reference1: &String = &string1;  
      let reference2: &String = &string1;  
        
      takes_ownership(reference1);  
      takes_ownership(reference2);  
        
      let _mut_ref: &mut String = &mut string1;  
    }  
      
    fn takes_ownership(_r1: &String){  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    这个例子完全没问题,因为在我们创建 _mut_ref 时,reference1reference2 已经超出了作用域。

    // 这段代码会导致错误  
    fn main(){  
      let mut string1: String = String::from("Hello World");  
      
      let reference1: &String = &string1;  
      let reference2: &String = &string1;  
      
      // 因为这一行  
      let _mut_ref: &mut String = &mut string1;  
      takes_ownership(reference1);  
      takes_ownership(reference2);  
        
    }  
      
    fn takes_ownership(_r1: &String){  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    结论

    在学习 Rust 的旅程中,第7天探讨了引用和借用,这是内存安全的基本概念。不可变引用允许在不转移所有权的情况下读取数据,而可变引用则允许修改,但必须遵守规则以确保独占访问和防止数据

  • 相关阅读:
    产品设计实战(上):Axure9绘制高保真原型
    python每日一题(模拟用户登录验证)
    虹科分享 | 谷歌Vertex AI平台使用Redis搭建大语言模型
    一文掌握Lambda表达式(下)
    创意无限,批量为视频添加个性化图片,让你的视频独一无二
    玻璃生产过程中的窑内压力高精度恒定控制解决方案
    MFC中字符串string类型和CString类型互转方法
    vue中的h函数与JSX语法
    C语言:打印几行机列的**符号
    shell入门概述
  • 原文地址:https://blog.csdn.net/Tory2/article/details/137949060