首页 > 其他分享 >RUST——借用与引用

RUST——借用与引用

时间:2023-04-12 10:23:00浏览次数:22  
标签:mut String r2 let 引用 借用 fn RUST

引用与借用

引用可以保证一个对象的引用作为参数而不是所有权

fn main() {
    let s1=String::from("hello");
    let len=cal_len(&s1);
    println!("The length of {} is {}",s1,len);
}
fn cal_len(s: &String)->usize{
    //s.push_str(", world");无法通过编译,因为属于借用
    s.len()
}

示意图如下:

同时,不允许改变借用的值
如果想要改变引用的值,可以使用“可变引用”
例如:

fn main() {
    let mut s = String::from("hello");

    change(&mut s);
}

fn change(some_string: &mut String) {
    some_string.push_str(", world");
}

可变引用存在一个限制,就是如果对一个变量具有可变引用,则不能再创建该变量的引用

fn main() {
    let mut s = String::from("hello");

    let r1 = &mut s;
    let r2 = &mut s;//let r2=&s;

    println!("{}, {}", r1, r2);
}

这一限制以一种非常小心谨慎的方式允许可变性,防止同一时间对同一数据存在多个可变引用。新 Rustacean 们经常难以适应这一点,因为大部分语言中变量任何时候都是可变的。这个限制的好处是 Rust 可以在编译时就避免数据竞争。数据竞争(data race)类似于竞态条件,它可由这三个行为造成:

  • 两个或更多指针同时访问同一数据。
  • 至少有一个指针被用来写入数据。
  • 没有同步数据访问的机制。
    数据竞争会导致未定义行为,难以在运行时追踪,并且难以诊断和修复;Rust 避免了这种情况的发生,因为它甚至不会编译存在数据竞争的代码
    但是多个不可变引用是可以的
fn main() {
    let mut s = String::from("hello");

    let r1 = &s; // 没问题
    let r2 = &s; // 没问题
    println!("{} and {}", r1, r2);
    // 此位置之后 r1 和 r2 不再使用

    let r3 = &mut s; // 没问题
    println!("{}", r3);
}

悬垂引用

在具有指针的语言中,很容易通过释放内存时保留指向它的指针而错误地生成一个 悬垂指针(dangling pointer),所谓悬垂指针是其指向的内存可能已经被分配给其它持有者。相比之下,在 Rust 中编译器确保引用永远也不会变成悬垂状态:当你拥有一些数据的引用,编译器确保数据不会在其引用之前离开作用域。
RUST会在编译的阶段阻止悬垂引用的出现,比如下面这段代码运行时会报错

fn main() {
    let reference_to_nothing = dangle();
}

fn dangle() -> &String {
    let s = String::from("hello");
//错误
    &s
}

修复bug的方式是将最后一行&s改变成s,相当于传回去所有权,因为传的是所有权,所以作用域内drop就不起作用了

总结引用

在任意给定时间,要么 只能有一个可变引用,要么 只能有多个不可变引用。
引用必须总是有效的

标签:mut,String,r2,let,引用,借用,fn,RUST
From: https://www.cnblogs.com/SaltyCheese/p/17308891.html

相关文章

  • Rust 资源汇总
    基础库tokiochronoUI库PCslint-uitaruiWebyew嵌入式slint-uiWeb库rocket数据库ormdieselsqlx......
  • RUST——控制流(if/loop/while)
    1.if语句下面看一个示例:fnmain(){letnumber=6;ifnumber%4==0{println!("numberisdivisibleby4");}elseifnumber%3==0{println!("numberisdivisibleby3");}elseifnumber%2==0{......
  • C++核心编程之-引用
    引用引用的基本使用作用:给变量起别名语法:数据类型&别名=原名引用的注意事项引用必须初始化引用在初始化后,不可以改变示例:#include<iostream>usingnamespacestd;intmain(){ inta=30; intb=50; //int&c;//这行错误,引用必须初始化 int&c=a......
  • 借用gcc内置函数帮助C来实现函数重载
    借用gcc内置函数__builtin_choose_expr和__builtin_types_compatible_p可以帮助c来实现函数重载。首先对这两个函数功能做下介绍__builtin_choose_expr(expr,expr1,expr2)与c语言:?运算符有些类似,如果expr表达式为真,那么返回expr1,否则返回expr2_builtin_types_compatible_p(ty......
  • Rust编程语言入门之cargo、crates.io
    cargo、crates.io本章内容通过releaseprofile来自定义构建在https://crates.io/上发布库通过workspaces组织大工程从https://crates.io/来安装库使用自定义命令扩展cargo一、通过releaseprofile来自定义构建releaseprofile(发布配置)releaseprofile:是预......
  • rust基础(上)
    定义变量fnmain(){ letnumber=3; letfood="事物"; letcheck=true; println!("thenumberis:{}",number); println!("thefoodis:{}",food); println!("thecheckis:{}",check); //设定整形类型 letnumber2:i32=-300;//i32代表有符号......
  • Rust 的 parse() 是一个用于将字符串解析为其他类型的方法
    在Rust中,parse()是一个用于将字符串解析为其他类型的方法。例如,可以将字符串解析为整数、浮点数或布尔值等。在这个例子中,parse()方法被用来将用户从标准输入中读取的字符串(即变量input_num)解析为整数类型。需要注意的是,parse()方法返回一个Result枚举类型,因为解析字符串......
  • Rust入门, 猜字游戏!
    userand::Rng;//随机数usestd::cmp::Ordering;//枚举对比cmpusestd::io;//io输入输出获取fnmain(){println!("这是一个猜字游戏!");//rand::thread_rng()是获取一个本地线程作为随机数函数使用,gen_range()是获取一个范围内的随机数生成letr......
  • Rust语言 , string(&str) 和 String 区别
    在Rust中,string表示字符串切片类型(&str),可以用于引用字符串数据。而String则是字符串类型,是一种可变的字符串,可以创建、修改和销毁。具体来说,string是Rust的核心语言类型之一,它是一个不可变的字符串切片类型,通常用于引用已有的字符串数据。由于字符串切片是不可变的,因此不......
  • Rust 关键词
    在Rust中,以下是所有的关键词列表,以及它们的作用和用途:as:类型转换关键字,用于将一个类型转换为另一个类型。async:异步函数关键字,用于定义异步函数。await:等待异步结果关键字,用于等待异步函数的执行结果。break:循环控制关键字,用于跳出当前的循环语句。const:常量声明关键字......