1. fn main() {
  2. let s1 = String::from("hello");
  3. let len = calculate_length(&s1);
  4. println!("The length of '{}' is {}.", s1, len);
  5. }
  6. fn calculate_length(s: &String) -> usize { // s is a reference to a String
  7. s.len()
  8. } // 这里,s 离开了作用域。但因为它并不拥有引用值的所有权,
  9. // 所以什么也不会发生

需求:我们必须将 String 返回给调用函数,以便在调用 calculatelength 后仍能使用 String,因为 String 被移动到了 calculate_length 内。
引用(_reference
)像一个指针,因为它是一个地址,我们可以由此访问储存于该地址的属于其他变量的数据。与指针不同,引用确保指向某个特定类型的有效值
image.png
借用borrowing)是创建一个引用的行为。只能用,不能改。

可变引用

  1. fn main() {
  2. let mut s = String::from("hello");
  3. change(&mut s);
  4. }
  5. fn change(some_string: &mut String) {
  6. some_string.push_str(", world");
  7. }

可变引用mutable reference)允许我们修改一个借用的值。可变引用有一个很大的限制:在同一时间只能有一个对某一特定数据的可变引用。这些尝试创建两个 s 的可变引用的代码会失败:

  1. let mut s = String::from("hello");
  2. let r1 = &mut s;
  3. let r2 = &mut s;
  4. println!("{}, {}", r1, r2);

第一个可变的借入在 r1 中,并且必须持续到在 println! 中使用它,但是在那个可变引用的创建和它的使用之间,我们又尝试在 r2 中创建另一个可变引用,该引用借用与 r1 相同的数据。
这个限制的好处是 Rust 可以在编译时就避免数据竞争。数据竞争data race)类似于竞态条件,它可由这三个行为造成:

  • 两个或更多指针同时访问同一数据。
  • 至少有一个指针被用来写入数据。
  • 没有同步数据访问的机制。 ```rust let mut s = String::from(“hello”);

let r1 = &s; // 没问题 let r2 = &s; // 没问题 let r3 = &mut s; // 大问题

println!(“{}, {}, and {}”, r1, r2, r3);

  1. 我们也不能在拥有不可变引用的同时拥有可变引用。
  2. <a name="WekQl"></a>
  3. ## 悬垂引用
  4. 在具有指针的语言中,很容易通过释放内存时保留指向它的指针而错误地生成一个 **悬垂指针**(dangling pointer),所谓悬垂指针是其指向的内存可能已经被分配给其它持有者。
  5. ```rust
  6. fn main() {
  7. let reference_to_nothing = dangle();
  8. }
  9. fn dangle() -> &String { // dangle 返回一个字符串的引用
  10. let s = String::from("hello"); // s 是一个新字符串
  11. &s // 返回字符串 s 的引用
  12. } // 这里 s 离开作用域并被丢弃。其内存被释放。
  13. // 危险!
  1. $ cargo run
  2. Compiling ownership v0.1.0 (file:///projects/ownership)
  3. error[E0106]: missing lifetime specifier
  4. --> src/main.rs:5:16
  5. |
  6. 5 | fn dangle() -> &String {
  7. | ^ expected named lifetime parameter
  8. |
  9. = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
  10. help: consider using the `'static` lifetime
  11. |
  12. 5 | fn dangle() -> &'static String {
  13. | ~~~~~~~~
  14. For more information about this error, try `rustc --explain E0106`.
  15. error: could not compile `ownership` due to previous error

引用的规则

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