本土建站工作室,北京百度seo工作室,网站开发好学不,企业老板培训课程上一章的内容中我们讨论了Rust的所有权系统#xff0c;当我们不想移动值的所有权时#xff0c;我们可以使用引用和借用#xff0c;而这正是本章想要讨论的问题。
引用#xff08;References#xff09;
引用允许你访问或修改数据而无需获取数据的所有权。在 Rust 中当我们不想移动值的所有权时我们可以使用引用和借用而这正是本章想要讨论的问题。
引用References
引用允许你访问或修改数据而无需获取数据的所有权。在 Rust 中有两种类型的引用
不可变引用T 它允许你读取数据但不能修改它。你可以同时拥有多个不可变引用。当存在不可变引用时不能再有可变引用。 可变引用mut T 它允许你读取和修改数据。同一时间只能有一个可变引用指向同一数据。当存在可变引用时不能再有其他可变或不可变引用为了防止写竞争或读取数据时数据改变。 如上图所示 在多个线程中如果都存在对同一个值的引用时 在没有锁的情况下 对同一个变量进行多个可变引用显然是不安全的。
借用Borrowing
借用是指使用引用来访问数据的行为。当你创建一个引用时实际上是在“借用”值。借用规则如下
数据的所有者不变当你借用一个值时该值的所有权不会转移。作用域和生命周期引用必须在其所指向的数据的作用域内有效。这就是 Rust 中的生命周期lifetime概念。
引用使用示例
let s1 String::from(abc);
do_stuff(s1);
println!({}, s1);fn do_stuff(s: String) {// do stuff
}上面的代码中 我们还是创建了一个do_stuff()函数 与上一章不同的是 我们这个函数接受的参数是一个字符串的引用 String前面的符号表示这是一个String类型的引用 因此当调用该函数时我们传递给他的是对s1的引用 而s1依然保留了对它的值的所有权。do_stuff()借用了一个对值的引用它将引用而不是值移动到了函数中 在函数的作用域结束时 引用被销毁我们的借用行为也在此时结束。在函数执行完以后我们还可以正常的使用s1, 因为其值的所有权没有被移动过。
从内存的视角出发 当创建一个指向s1的引用时 Rust会创建一个指向s1的指针。 但在Rust中我们几乎从来不会谈论指针的行为因为Rust语言在很大程度上会自动处理他们的创建和销毁Rust中的有一个生命周期的概念就是用来确保指针始终有效。 Rust的编译器可以保证 不会让用户创建一个引用的存活时间超过它引用的源数据的存活时间并且指针永远不能指向Null。
可变与不可变引用
引用与变量一样 默认是不可变的这意味着即使被引用的值是可变的也不能直接通过引用来修改它例如下面这段代码
let mut s1 String::from(abc);
do_stuff(s1);fn do_stuff(s: String) {s.insert_str(0, Hi, ); // Error
}虽然s1被声明为可变的 但是它的引用默认是不可变的因此在函数中试图修改s1的值编译器就会报错。想要通过引用修改被引用的值可以将引用声明为可变引用
let mut s1 String::from(abc);
do_stuff(mut s1);fn do_stuff(s: mut String) {s.insert_str(0, Hi, );
}注意可变引用的格式有些许特别 mut 变量/类型
解引用
注意到了吗在上面的例子中的函数中修改s的值的时候并没有对其先解引用。我们直接使用了.操作符来访问可变引用上的字符串函数就像我们在对被引用的值本身进行操作一样。
在Rust中函数或字段的.运算符会自动对引用进行解引用获取到最终被引用的值。这样的话在我们使用.运算符的时候就不用费劲搞清楚某个变量到底是一个值还是一个引用甚至是一个引用的引用了。
那怎么样可以手动的进行解引用的操作呢和大多数语言一样在前面加上一个*即可, 解引用操作符的优先级很低因此需要加上( )
let mut s1 String::from(abc);
do_stuff(mut s1);fn do_stuff(s: mut String) {(*s).insert_str(0, Hi, );
}注意上面说的是在.运算符的情况下 Rust会进行自动的解引用 对于大多数的其他运算符例如赋值运算是需要手动进行解引用的
let mut s1 String::from(abc);
do_stuff(mut s1);fn do_stuff(s: mut String) {s.insert_str(0, Hi, );*s String::from(Replacement);
}小结
本章介绍了引用和借用的含义以及使用方法让我们来简单回顾一下
x // 变量
x //变量的不可变引用
mut x // 变量的可变引用i32 // 类型
i32 // 该类型的不可变引用的类型
mut i32 // 该类型的可变引用的类型x: mut i32 // x是某个值的可变引用
*x // *x解引用获取到被引用的值 可变x: i32 // x是某个值的不可变引用
*x // 解引用获取到被引用的值不可变下一章将开始介绍Rust中的结构体。