当前位置: 首页 > article >正文

【Rust】引用与借用

目录

思维导图

1. 引用与借用的基本概念

1.1. 引用示例

2. 借用的规则

2.1. 可变借用示例

2.2. 借用的限制

3. 引用的生命周期


思维导图

1. 引用与借用的基本概念

  • 引用的定义引用是一种指向数据的指针,但与裸指针不同,Rust的引用在编译时受到严格的规则约束,确保其始终指向有效的内存区域。引用分为不可变引用(&T)和可变引用(&mut T)。
  • 借用的意义借用是指在不获取数据所有权的情况下,通过引用访问或修改数据的过程。借用机制允许在多个上下文中共享数据,同时避免数据竞争和内存安全问题。

1.1. 引用示例

  • 示例1:计算字符串长度
    fn main() {
        let text = String::from("hello");
        let length = calculate_string_length(&text); // 传递不可变引用
        println!("The length of '{}' is {}.", text, length);
    }
    
    // 计算字符串长度的函数
    fn calculate_string_length(s: &String) -> usize {
        s.len() // 通过引用访问数据
    }
    • 在这个示例中,calculate_string_length函数接受一个字符串的引用&text,而不是直接获取String的所有权。这允许main函数在调用后继续使用text

2. 借用的规则

  • 不可变借用当一个值被不可变引用借用时,该值在借用期间不能被修改。允许多个不可变引用同时存在,确保数据的一致性。
  • 可变借用若要修改借用的值,必须使用可变引用&mut。Rust强制要求在同一时间只能有一个可变引用,或者多个不可变引用,但两者不能共存。这一规则防止了数据竞争的发生。

2.1. 可变借用示例

  • 示例2:修改借用的字符串
    fn main() {
        let mut s = String::from("hello");
        append_text(&mut s); // 传递可变引用
        println!("{}", s); // 输出修改后的字符串
    }
    
    // 修改字符串的函数
    fn append_text(s: &mut String) {
        s.push_str(", world"); // 通过可变引用修改数据
    }
    • 在这个示例中,s被声明为可变,并通过&mut s传递给append_text函数,允许对s进行修改。

2.2. 借用的限制

  • 多个可变引用的限制Rust禁止在同一作用域内同时存在多个可变引用,以防止数据竞争(data races)。数据竞争可能导致未定义行为,因此Rust在编译时严格检查此类问题。
  • 可变与不可变引用的限制:当同一个值有一个不可变引用时,便不能再拥有一个可变引用。
  • 示例3:多个可变引用的错误
    fn main() {
        let mut message = String::from("hello");
    
        let first_ref = &mut message; // 第一个可变引用
        // let second_ref = &mut message; // 取消注释会导致编译错误
    
        println!("First reference: {}", first_ref);
        // println!("Second reference: {}", second_ref); // 无法同时使用两个可变引用
    }
    • 此代码尝试同时创建两个可变引用,导致编译错误。

3. 悬空引用

  • Rust通过生命周期(lifetime)机制确保引用在使用期间始终指向有效的内存区域,避免了悬空引用的问题。生命周期是Rust编译器在编译时进行静态检查的重要工具。

  • 示例4:悬空引用的错误
    fn main() {
        // let dangling_ref = create_dangling_reference(); // 取消注释会导致编译错误
        // println!("{}", dangling_ref); // 无法使用悬空引用
    }
    
    // 尝试返回局部变量引用的函数
    fn create_dangling_reference() -> &String {
        let s = String::from("hello");
        &s // 编译错误:返回局部变量的引用
    }
    • 该示例试图返回一个局部变量的引用,导致编译错误,因为&s在函数结束后S会被释放。

tips: 

  • 在任何时候,你都可以拥有要么一个可变引用要么任意数量的不可变引用。
  • 引用必须始终有效。

补充:常见数据竞争:

  • 两个或多个指针同时访问相同的数据。
  • 至少有一个指针正在用于写入数据。
  • 没有使用任何机制来同步对数据的访问。


http://www.kler.cn/a/501399.html

相关文章:

  • 备战蓝桥杯:树的存储与遍历(dfs和bfs)
  • Ubuntu Server 24.04 配置静态IP
  • 改进萤火虫算法之七:基于自适应机制的萤火虫算法(Adaptive Firefly Algorithm, AFA)
  • springboot使用Easy Excel导出列表数据为Excel
  • MVC执行流程
  • Qt监控系统远程网络登录/请求设备列表/服务器查看实时流/回放视频/验证码请求
  • uniapp区域滚动——上划进行分页加载数据(详细教程)
  • Python脚本自动创建GitHub标签
  • 制造企业“数字化转型”典型场景参考
  • Excel多层嵌套IF条件写法
  • Android中的蓝牙:BLE、经典蓝牙
  • Golang中遇到“note module requires Go xxx”后的解决方案,不升级Go版本!
  • 数据结构与算法之二叉树: LeetCode 572. 另一棵树的子树 (Ts版)
  • 1、什么是GO
  • IntelliJ IDEA 优化设置
  • 啥!GitHub Copilot也免费使用了
  • 晨辉面试抽签和评分管理系统之七:面试成绩核算的三种方式
  • matlab编写分段Hermite插值多项式
  • linux新磁盘做分区(GPT分区表)
  • MySQL教程之:批量使用mysql
  • MyBatis-Plus自动填充
  • Node.js——fs(文件系统)模块
  • Android车机DIY开发之软件篇(九)默认应用和服务修改
  • gesp(C++四级)(16)洛谷:B4069:[GESP202412 四级] 字符排序
  • Oracle 23ai新特性:表值构造函数
  • 《自动驾驶与机器人中的SLAM技术》ch7:基于 ESKF 的松耦合 LIO 系统