首页 > 其他分享 >Rust简易入门(五)

Rust简易入门(五)

时间:2024-03-30 20:03:44浏览次数:18  
标签:生命周期 入门 self 简易 let 引用 str fn Rust

Borring && Borrow Checker && Lifetime

Borrowing(引用的函数式声明)

一个玩意的两种描述

引用(reference):

  1. 引用是一种变量的别名,通过 & 符号来创建(非所有权)

  2. 引用可以是不可变的(&T)或可变的(&mut T)

  3. 引用允许在不传递所有权的情况下访问数据,他们是安全且低开销的

借用(Borrowing):

  1. 借用是通过引用(Reference)来借用(Borrow)数据,从而在一段时间内访问数据而不借用它

  2. 借用氛围可变借用和不可变借用。可变借用(&mut)允许修改数据,但在生命周期内只能有一个可变借用。不可变借用(&)允许多个同时存在,但不允许修改数据

Borrow Checker

  1. 不可变引用规则:
    在任何给定的时间,要么有一个可变引用,要么有多个不可变引用,但不能同时存在可变引用与不可变引用。这确保了在同一时间内只有一个地方对数据进行修改,或者有多个地方同时读取数据

  2. 可变引用规则
    在任何给定的时间,只能有一个可变引用来访问数据。这防止了并发修改相同数据的问题,从而防止数据竞争

  3. 引用的生命周期必须在被引用的数据有效时间范围内。这防止了悬垂引用,即引用的数据已经被销毁,但引用仍然存在

  4. 可变引用与不可变引用不互斥
    可以同时存在多个不可变引用,因为不可变引用不会修改数据,不会影响到其他引用。但不可变引用与可变引用之间是互斥的。

fn main(){
    let mut s = String::from("Hello");
    
    let r1 = &s;
    let r2 = &s;
    println!("{} {}", r1, r2);
    
    let r3 = &mut s;
    println!("{}", r3);
    
    let result: &str;
    {
        // result = "hello";   // 初始化不影响生命周期
        let r4 = &s;
        result = ff(r4);
        
    }
    println!("{}", result);
}

fn ff<'a>(s: &'a str) -> &'a str {
    s
}

Lifetime 与 函数

大多数情况下,生命周期是隐式且被推断的

生命周期的主要目的是防止悬垂引用

关于"悬垂引用”的概念是指,引用指向的数据在代码结束后被释放,但引用仍然存在。生命周期的引入有助于确保引用的有效性,防止程序在运行时出现悬垂引用的情况。通过生命周期的推断,Rust能够在编译时检查代码,确保引用的有效性而不是在运行时出现悬垂引用的错误。

编译器在没有显式注解的情况下,使用三个规则来推断这些生命周期:

  1. 第一个规则是每个作为引用的参数都会得到它自己的生命周期参数。

  2. 第二个规则是,如果只有一个输入生命周期参数,那么该生命周期将被分配给所有输出生命周期参数(该生命周期将分配给返回值)。

  3. 第三个规则是,如果有多个输入生命周期参数,但其中一个是对self或不可变se|f的引用时。因为在这种情况下它是一个方法,所以se|f的生命周期被分配给所有输出生命周期 参数

fn longest<'a>(s1: &'a str, s2: &'a str) -> &'a str {
    if s1.len() > s2.len() {
        s1
    } else {
        s2
    }
}

fn longest_str<'a, 'b, 'out>(s1: &'a str, s2: &'b str) -> &'out str 
where 
    'a : 'out,
    'b : 'out,
{
    if s1.len() > s2.len() {
        s1
    } else {
        s2
    }
}

fn no_need(s: &'static str, s1: &str) -> &'static str{
    s
}

fn main(){
    println!("no need {}", no_need("hh", "nn"));
    
    let s1 = "hello world";
    let s2 = "hello";
    println!("longest {}", longest(s1, s2));
}

Lifetime 与 Struct

结构体的引用

  • 在结构体中的引用需要标注生命周期

  • 结构体的方法(&self等)不需要标注生命周期

struct MyStruct<'a>{
    text: &'a str,
}

impl<'a> MyStruct<'a>{
    fn get_length(&self) -> usize{
        self.text.len()
    }
    fn modify_data(&mut self) {
        self.text = "world2";
    }
}

struct StringHolder{
    data: String,
}

impl StringHolder{
    fn get_length(&self) -> usize{
        self.data.len()
    }
    fn get_reference<'a>(&'a self) -> &'a String{
        &self.data
    }
    fn get_ref(&self) -> &String{
        &self.data
    }
}

fn main(){
    let str1 = String::from("hello");
    let mut x = MyStruct{
        text: str1.as_str(),
    };
    
    x.modify_data();
    println!("{}", x.get_length());
    
    
    let y = StringHolder{
        data: "hello".to_owned(),
    };
    println!("{}",y.get_reference());
    println!("{}",y.get_ref());
}

标签:生命周期,入门,self,简易,let,引用,str,fn,Rust
From: https://www.cnblogs.com/moguw/p/18105924/rust-base-5

相关文章

  • Rust简易入门(四)
    错误处理之:Result、Option以及panic!宏Rust中的错误可以分为两种Recoverableerror:有返回类型返回Result类型返回Option类型Unrecoverabletype:没有返回类型,直接崩溃panicmacro将终止当前线程Result是一个枚举类型,有两个变体:Ok和Err。它通常用于表示函数的执行结......
  • Rust简易入门(五)
    Borring&&BorrowChecker&&LifetimeBorrowing(引用的函数式声明)一个玩意的两种描述引用(reference):引用是一种变量的别名,通过&符号来创建(非所有权)引用可以是不可变的(&T)或可变的(&mutT)引用允许在不传递所有权的情况下访问数据,他们是安全且低开销的借用(Borrowing):......
  • (七)Rust 通用的编程概念
    变量与可变性在Rust语言中,声明变量是使用let关键字,而且变量默认是不可改变的,一旦值被绑定在一个名称上,就不能给这个变量重新赋值,如果重新赋值的话,就会在编译的时候报错。这是Rust提供给我们的众多优势之一,让我们可以充分利用Rust提供的安全性和简单并发性来编写代码......
  • (八)Rust 函数和注释
    函数在Rust里,声明函数使用fn关键字,按照惯例,针对函数和变量名,Rust使用snakecase命名规范:所有的字母都是小写,单词之间使用下划线分开,例如:函数的参数定义函数时里边定义的参数,叫形参(parameters)调用函数时传递的具体参数,叫实参(arguments)在函数签名里,必须声明每个参数的类......
  • PS从入门到精通视频各类教程整理全集,包含素材、作业等(3)
    PS从入门到精通视频各类教程整理全集,包含素材、作业等最新PS以及插件合集,可在我以往文章中找到由于阿里云盘有分享次受限制和文件大小限制,今天先分享到这里,后续持续更新 中级教程https://www.alipan.com/s/unii5YxtM8B提取码:4ji2点击链接保存,或者复制本段内容,打开「阿......
  • PS从入门到精通视频各类教程整理全集,包含素材、作业等(3)复发
    PS从入门到精通视频各类教程整理全集,包含素材、作业等最新PS以及插件合集,可在我以往文章中找到由于阿里云盘有分享次受限制和文件大小限制,今天先分享到这里,后续持续更新 中级教程https://www.alipan.com/s/unii5YxtM8B提取码:4ji2点击链接保存,或者复制本段内容,打开「阿......
  • C++入门(一)
    目录命名空间:为什么要提出命名空间?命名空间的定义:命名空间的使用:加命名空间名称及作用域限定符:使用using将命名空间中某个成员引入:使用usingnamespace命名空间名称引用:C++输入&输出:库的导入:使用说明:输入和输出:输入流:输出流:缺省参数:缺省参数的概念:缺省参数的......
  • 中间件 ZK分布式专题与Dubbo微服务入门 6-3 同步异步创建zk节点
    0课程地址https://coding.imooc.com/lesson/201.html#mid=12719 1重点关注1.1本节内容javaapi客户端新增临时节点和永久节点 1.2javaapi新增节点同步调用/***同步或者异步创建节点,都不支持子节点的递归......
  • Rust简易入门(二)
    Rust内存管理模型"Stoptheworld'"是与垃圾回收(GarbageCollection)相关的术语,它指的是在进行垃圾回收时系统暂停程序的运行。这个术语主要用于描述一种全局性的暂停,即所有应用线程都被停止,以便垃圾回收器能够安全地进行工作。这种全局性的停止会导致一些潜在的问题,特别是对于......
  • Rust简易入门(三)
    Rust的流程控制主要包括条件语句(if、else、elseif)、循环语句(for、while)和跳转语句(break、continue、return)。这些语句使程序员能够根据特定的条件或循环执行代码块,从而实现各种复杂的逻辑控制。例如,if语句允许程序员根据条件执行代码,而for和while循环则用于重复执行代码块,直到满......