关于Rust借用与解引用的技术疑问(附代码示例)
Hey there! Let's break down your questions about the provided Rust code step by step—this stuff can be tricky at first, but once you wrap your head around Box<T> as a smart pointer with ownership semantics, it all clicks into place.
1. Why do we need the & when calling borrow_i32(&boxed_i32);? Isn't boxed_i32 already a pointer?
Great question! First, let's clarify: Box<i32> is a smart pointer type, not a raw pointer. It's a stack-allocated value that contains an address pointing to heap-allocated i32 data—but crucially, it behaves like a regular owned value in Rust (with its own ownership rules), not like a bare *const i32 pointer.
The borrow_i32 function expects a parameter of type &i32 (a reference to an i32). If you tried to pass boxed_i32 directly without the &, you'd be trying to move ownership of the Box<i32> into the function—but the function doesn't accept Box<i32>, it accepts &i32—so the compiler would throw a type mismatch error.
When you add the & to get &boxed_i32, you're creating a reference to the Box<i32> value itself. Then Rust uses deref coercion (a core Rust feature) to automatically convert &Box<i32> into &i32. This works because Box<T> implements the Deref trait with Target = T, which tells Rust that a reference to a Box<T> can be treated like a reference to T.
2. Why do we need the & in let _ref_to_i32: &i32 = &boxed_i32;? Isn't boxed_i32 already an address?
Again, boxed_i32 is not a raw address—it's a Box<i32> value (stack-allocated) that holds an address. If you wrote just boxed_i32 on the right-hand side, you'd be trying to move the Box<i32> into the variable, but we want a reference to the underlying i32 instead.
By writing &boxed_i32, we create a &Box<i32> reference. Then deref coercion kicks in again: Rust automatically converts that &Box<i32> to &i32, which matches the type annotation on the left-hand side.
If you prefer to be explicit, you could also write &*boxed_i32 (first dereference the Box<i32> to get the i32, then take a reference to it)—this does exactly the same thing as &boxed_i32, but makes the dereferencing step visible.
3. Why can borrow_i32 accept references to both Box<i32> and i32?
This is all thanks to deref coercion! Let's break down each case:
- When you pass
&stacked_i32,stacked_i32is ani32, so&stacked_i32is directly a&i32—this matches the function's parameter type perfectly. - When you pass
&boxed_i32, you're passing a&Box<i32>. SinceBox<T>implementsDeref<Target = T>, Rust automatically "unwraps" the reference to theBoxinto a reference to the inneri32, making the type match&i32.
Deref coercion is designed to make smart pointers feel as natural to use as regular values—you don't have to manually dereference them every time you want to access the underlying data.
A quick note on the error in your code
The error when calling eat_box_i32(boxed_i32) inside the block makes sense once you understand borrowing rules: _ref_to_i32 is a reference to the i32 inside boxed_i32 (created via deref coercion). As long as that reference exists (is in scope), Rust prevents you from moving ownership of boxed_i32 (which would destroy the underlying i32 and leave _ref_to_i32 as a dangling reference). Once _ref_to_i32 goes out of scope at the end of the block, the borrow ends, and you can safely move boxed_i32 to eat_box_i32.
内容的提问来源于stack exchange,提问作者Liviu




