借用
多数情况下,我们更希望能访问数据,同时不取得其所有权。为实现这点,Rust 使用了借用(borrowing)机制。对象可以通过引用(&T
)来传递,从而取代通过值(T
)来传递。
编译器(通过借用检查)静态地保证了引用总是指向有效的对象。也就是说,当存在引用指向一个对象时,该对象不能被销毁。
// 此函数取得一个 box 的所有权并销毁它 fn eat_box_i32(boxed_i32: Box<i32>) { println!("Destroying box that contains {}", boxed_i32); } // 此函数借用了一个 i32 类型 fn borrow_i32(borrowed_i32: &i32) { println!("This int is: {}", borrowed_i32); } fn main() { // 创建一个装箱的 i32 类型,以及一个存在栈中的 i32 类型。 let boxed_i32 = Box::new(5_i32); let stacked_i32 = 6_i32; // 借用了 box 的内容,但没有取得所有权,所以 box 的内容之后可以再次借用。 // 译注:请注意函数自身就是一个作用域,因此下面两个函数运行完成以后, // 在函数中临时创建的引用也就不复存在了。 borrow_i32(&boxed_i32); borrow_i32(&stacked_i32); { // 取得一个对 box 中数据的引用 let _ref_to_i32: &i32 = &boxed_i32; // 报错! // 当 `boxed_i32` 里面的值之后在作用域中被借用时,不能将其销毁。 eat_box_i32(boxed_i32); // 改正 ^ 注释掉此行 // 在 `_ref_to_i32` 里面的值被销毁后,尝试借用 `_ref_to_i32` //(译注:如果此处不借用,则在上一行的代码中,eat_box_i32(boxed_i32)可以将 `boxed_i32` 销毁。) borrow_i32(_ref_to_i32); // `_ref_to_i32` 离开作用域且不再被借用。 } // `boxed_i32` 现在可以将所有权交给 `eat_box_i32` 并被销毁。 //(译注:能够销毁是因为已经不存在对 `boxed_i32` 的引用) eat_box_i32(boxed_i32); }