Rust区块琏开发——引用与借用

引用

  1. &符号表示共享引用:允许你在引用某些值而不取得其所有权。
fn main() 
{
    
    
    let s1 = "rust".to_string();
    let len = str_len(&s1);//传入的是s1的引用

    print!("{}  {}", s1.len(),len);

}

fn str_len(str : & String) -> usize
{
    
    
    str.len()
}
  1. 如果要在共享引用的状态要改变数据的值,则会引起恐慌。通俗的理解是,你借用了别人的东西,正常情况下,你是不可以对你借用的东西做任何改动。把引用做为参数的行为,在rust里面也称为借用。
fn str_len(str : & String) -> usize
{
    
    
    str.pop();//想要改变引用的数据的值
    str.len()
}

这里编译时不通过的,会报以下错误:
在这里插入图片描述
3. 如果想在引用的时候能改变数据里面的值,则需要在数据前面加上mut指明传入的数据是可变的。

fn main() 
{
    
    
    let mut s1 = "rust".to_string();
    let len = str_len(&mut s1);

    print!("{}  {}", s1.len(),len);

}

fn str_len(str : &mut String) -> usize
{
    
    
    str.push_str(",hello");
    str.len()
}

4.Rust的设计原则是,同⼀作⽤域内,对于某⼀个对象的引⽤,只允许存在两种情况:要么只有⼀个可变引⽤,要么同时存在多个共享引⽤,共享引⽤不允许修改内容,可变引⽤才有修改权限。

 let mut s1 = "rust".to_string();
 let s2 = &mut s1;
 let s3 = &mut s1;

 print!("{} {}",s2,s3);

会报以下错误:

error[E0499]: cannot borrow `s1` as mutable more than once at a time
 --> src/main.rs:7:14
  |
6 |     let s2 = &mut s1;
  |              ------- first mutable borrow occurs here
7 |     let s3 = &mut s1;
  |              ^^^^^^^ second mutable borrow occurs here
8 | 
9 |     print!("{} {}",s2,s3);
  |                    -- first borrow later used here

这样做的原因是为防止数据竞争,数据竞争在编译时很难被发现,只有在运行时才出现,rust的单个可变引用在根本上解决了这种问题,可能会发生数据竞争的几种情况:

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

5.但可以通过创建新的作用域,非同时创建多个可变引用。

let mut s1 = "rust".to_string();

 {
    
    
      let s2 = &mut s1;
 }

let s3 = &mut s1;

6.不可以同时拥有一个可变的引用和一个不可变的引用。

let mut s1 = "rust".to_string();

let s2 = &s1;

let s3 = &mut s1;

print!("{}  {}", s2.len(),s3.len());

报错:

error[E0502]: cannot borrow `s1` as mutable because it is also borrowed as immutable
  --> src/main.rs:9:14
   |
7  |     let s2 = &s1;
   |              --- immutable borrow occurs here
8  | 
9  |     let s3 = &mut s1;
   |              ^^^^^^^ mutable borrow occurs here
...
16 |     print!("{}  {}", s2.len(),s3.len());
   |                      -------- immutable borrow later used here
  1. 在Rust中,编译器可以保证引用永远都不是悬空引用。
    悬空引用是指一个指针引用了内存中的某个地址,而这块内存可能已经释放并分配给其它数据使用,在rust里,如果引用了某些数据,编译器将保证在引用离开作用域之前数据不会离开作用域。
fn main() 
{
    
    
    let s = dangle_ref();
}

fn dangle_ref() -> &String
{
    
    
    let str = "rust".to_string();
    &str
}

报错:

error[E0106]: missing lifetime specifier
 --> src/main.rs:8:20
  |
8 | fn dangle_ref() -> &String
  |                    ^ expected named lifetime parameter
  |
  = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
  |
8 | fn dangle_ref() -> &'static String
  |                    ~~~~~~~~

这里的str的生命周期出了函数作用域后就不起作用了。

8.rust 与C++的区别在于,C++中有一种引用,并且是可变的,但rust中的类型,如果没有实现Copy trait,那么在此类型的变量赋值、函数入参、函数返回值都是move语义。C++ 11 之后也有move语法。

猜你喜欢

转载自blog.csdn.net/matt45m/article/details/125673919