借用

多数情况下,我们更希望能访问数据,同时不取得其所有权。为实现这点,Rust 使用 了借用(borrowing)机制。对象可以通过引用(&T)来传递,从而取代通过 值(T)来传递。

编译器(通过借用检查)静态地保证了引用总是指向有效的对象。也就是说,当存在 引用指向一个对象时,该对象不能被销毁。

  1. // 此函数取得一个 box 的所有权并销毁它
  2. fn eat_box_i32(boxed_i32: Box<i32>) {
  3. println!("Destroying box that contains {}", boxed_i32);
  4. }
  5. // 此函数借用了一个 i32 类型
  6. fn borrow_i32(borrowed_i32: &i32) {
  7. println!("This int is: {}", borrowed_i32);
  8. }
  9. fn main() {
  10. // 创建一个装箱的 i32 类型,以及一个存在栈中的 i32 类型。
  11. let boxed_i32 = Box::new(5_i32);
  12. let stacked_i32 = 6_i32;
  13. // 借用了 box 的内容,但没有取得所有权,所以 box 的内容之后可以再次借用。
  14. // 译注:请注意函数自身就是一个作用域,因此下面两个函数运行完成以后,
  15. // 在函数中临时创建的引用也就不复存在了。
  16. borrow_i32(&boxed_i32);
  17. borrow_i32(&stacked_i32);
  18. {
  19. // 取得一个对 box 中数据的引用
  20. let _ref_to_i32: &i32 = &boxed_i32;
  21. // 报错!
  22. // 当 `boxed_i32` 里面的值之后在作用域中被借用时,不能将其销毁。
  23. eat_box_i32(boxed_i32);
  24. // 改正 ^ 注释掉此行
  25. // 在 `_ref_to_i32` 里面的值被销毁后,尝试借用 `_ref_to_i32`
  26. //(译注:如果此处不借用,则在上一行的代码中,eat_box_i32(boxed_i32)可以将 `boxed_i32` 销毁。)
  27. borrow_i32(_ref_to_i32);
  28. // `_ref_to_i32` 离开作用域且不再被借用。
  29. }
  30. // `boxed_i32` 现在可以将所有权交给 `eat_i32` 并被销毁。
  31. //(译注:能够销毁是因为已经不存在对 `boxed_i32` 的引用)
  32. eat_box_i32(boxed_i32);
  33. }