Reputation: 1014
Is there any case where one would use str
without borrowing it? Does that even make sense?
I understand the difference between String
and &str
, but since there is &str
there must also be str
?
Upvotes: 3
Views: 532
Reputation: 879
Because str
is unsized (?Sized) meaning the size at compile time is not known. You can only use it in places where ?Sized
is allowed. That is the case in Box.
let s: &str = "any string";
let box: Box<str> = Box::from(s);
Because box allocates data on the heap, it does not care if the size of the type is not known at compile time.
You can see Box<str>
used in String::into_boxed_str, which is useful if you want to say, I'm finished with generating the string and don't want to be able to add anything to it. Additionally it removes the capacity field which String
needs, which saves a bit of memory. However I haven't really seen this used very much.
Most places where you will see a str
without the &
before are in traits with generic types. For example when implementing AsRef.
pub struct CustomString(String);
impl AsRef<str> for CustomString {
fn as_ref(&self) -> &str {
self.0.as_str()
}
}
Sidenote: str
behaves similarly to a slice [T]
it to is unsized (?Sized
).
Upvotes: 4
Reputation: 58715
You can't do much with a value of type str
, but there are plenty of cases where you would want to refer to the type str
.
Box<str>
or Rc<str>
- owned types, similar to String
, but can't be mutated to grow or re-allocate
Any time you want to accept an arbitrary type that can be viewed as a string, you could use constraints like T: Deref<Target = str>
, T: AsRef<str>
or T: Borrow<str>
. For example HashMap::get
has the following signature:
pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V> where
K: Borrow<Q>, // K is the key type for the HashMap
Q: Hash + Eq,
This means you can have a HashMap<String, i32>
, but access values with a &str
key, e.g. map.get("key")
. Here Q
would be inferred to be str
, but the k
argument would still be a &str
(&Q
).
The ?Sized
annotation means that Q
does not need to have a size known at compile-time, explicitly allowing unsized types like str
to be used.
Upvotes: 8