I was reading through the book section about String
s and found they were using &*
combined together to convert a piece of text. The following is what it says:
use std::net::TcpStream;
TcpStream::connect("192.168.0.1:3000"); // Parameter is of type &str.
let addr_string = "192.168.0.1:3000".to_string();
TcpStream::connect(&*addr_string); // Convert `addr_string` to &str.
In other words, they are saying they are converting a String
to a &str
. But why is that conversion done using both of the aforementioned signs? Should this not be done using some other method? Does not the &
mean we are taking its reference, then using the *
to dereference it?
In short: the *
triggers an explicit deref, which can be overloaded via ops::Deref
.
Look at this code:
let s = "hi".to_string(); // : String
let a = &s;
What's the type of a
? It's simply &String
! This shouldn't be very surprising, since we take the reference of a String
. Ok, but what about this?
let s = "hi".to_string(); // : String
let b = &*s; // equivalent to `&(*s)`
What's the type of b
? It's &str
! Wow, what happened?
Note that *s
is executed first. As most operators, the dereference operator *
is also overloadable and the usage of the operator can be considered syntax sugar for *std::ops::Deref::deref(&s)
(note that we recursively dereferencing here!). String
does overload this operator:
impl Deref for String {
type Target = str;
fn deref(&self) -> &str { ... }
}
So, *s
is actually *std::ops::Deref::deref(&s)
, in which the deref()
function has the return type &str
which is then dereferenced again. Thus, *s
has the type str
(note the lack of &
).
Since str
is unsized and not very handy on its own, we'd like to have a reference to it instead, namely &str
. We can do this by adding a &
in front of the expression! Tada, now we reached the type &str
!
&*s
is rather the manual and explicit form. Often, the Deref
-overload is used via automatic deref coercion. When the target type is fixed, the compiler will deref for you:
fn takes_string_slice(_: &str) {}
let s = "hi".to_string(); // : String
takes_string_slice(&s); // this works!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With