Reputation: 111
What I've been told is that once an object (in this cast sth
) implements the Drop
trait then it can use *
operator to call its deref()
method. So I think the result of using *
should be the same as the result of explicitly call deref()
. But I find in some cases the two results are not equal. For example:
use std::ops::Deref;
fn main() {
let sth = Box::new(5);
println!("{:p}", sth.deref());
println!{"{:?}", *sth};
}
I searched the docs and know that the signature of deref()
of Box
is (&self)->&T
. That means it should return a reference of inner value. However, *sth
looks like it is returning the inner value directly. Why are the two results not equal?
Upvotes: 4
Views: 1667
Reputation: 42492
As Chayim answered deref()
is used to get a reference to the inner item, which the *
then actually accesses.
However when it comes to Box
you won't find its behaviour regulated by any trait (at least as yet): Box
is a language item.
While unlike references it looks like a normal type it really has the same status, and lives at the core of the language itself. As a result, it can (and does) behave in ways no other type can.
One of these behaviours is the ability to move on dereference, which is completely unique to it (RFCs have been proposed for that in the past but AFAIK little progress has been made).
Although in your specific case that's not even involved: println!
will always reference its parameters, so
println!{"{:?}", *sth};
really does
let args = Args::new(&*sth);
and then you get the value because there is a blanket impl Display for &T where T: Display
which delegates to T
's implementation (and the same for Box
incidentally).
Which you can check by duplicating the line and seeing that it works fine, which it would not have if the value had been moved (and the box dropped).
Upvotes: 1
Reputation: 71430
*
is not the same as v.deref()
(or more exactly Deref::deref(&v)
) - it's more like *Deref::deref(&v)
(note the *
).
Regarding Box
specifically, it can move out of it, like:
let s = Box::new(String::new());
let moved_out = *s;
// s; // Error, moved out of the `Box`.
In either type, it creates a place - it can be *Deref::deref(&v)
or *DerefMut::deref_mut(&v)
, depending on whether mutable access is required.
Upvotes: 4