Your word is holding a reference to data inside s. Use to_owned or to_string to allocate a copy and cut the ties that bind word and s.
fn main() {
let mut s = String::from("Hello World!");
// let word : &str = first_word(&s);
let word : String = first_word(&s).to_string();
s.clear();
println!("first word is {}", word);
}
fn first_word(s: &String) -> &str {
s.split_whitespace().next().unwrap()
}
For other data types, .clone() may be sufficient to release an immutable borrow. It depends on how the type was designed. For &str, .clone() preserves the borrow, which is why .to_string() is used in that example.
No, doing so could make the immutable borrow dangling. For example, let's say first_word returns a sub-string of the input. Then s.clear() would clear the string, and word would be pointing into uninitialized memory.
I think you're asking if you can throw away the variable holding the immutable borrow. Sure, use a scope boundary (which I normally use), or possibly even drop(). You cannot throw away s before word, since s owns the allocated memory that word borrows from, so these two examples use and drop word before s.clear() is used.
fn main() {
let mut s = String::from("Hello World!");
{
let word = first_word(&s);
println!("first word is {}", word);
// Variable word dropped at end of scope, and
// its immutable borrow is released.
}
s.clear();
}
fn first_word(s: &String) -> &str {
s.split_whitespace().next().unwrap()
}
fn main() {
let mut s = String::from("Hello World!");
let word = first_word(&s);
println!("first word is {}", word);
// Variable word dropped, and
// its immutable borrow is released.
drop(word);
s.clear();
}
fn first_word(s: &String) -> &str {
s.split_whitespace().next().unwrap()
}
A reference disappears as soon as you stop using it, so there no need to explicitly remove one. Also shared reference are copy so attempting to drop one doesn't do anything.