"A slice is a kind of reference, so it does not have ownership."
The following code is simplified. It needs to return a slice using a match
. All but one match arm return a string slice. One arm needs to add single quotations around a slice, thus we turn to using format!
that returns String
. The String must then convert to &str
.
The error shows that the resulting slice is referenced by the temporary String in the match arm.
11 | ret
| ^^^ returns a value referencing data owned by the current function
The simplified code as follows. Note we are not using literals but a &str
returned from a third party crate.
fn my_func(input: &str) ->&str {
let ret =
match input {
"a" => "Apha", // in fact, a &str from a crate
_ => format!("'{}'", "Quoted" ).as_str(),
};
ret
}
&str
is desired because that &str
is then pushed using push_str()
.
fn main() {
let mut s = String::new();
s.push_str(my_func("a"));
...
What is your recommendation for copying the str or derefencing the temp string within the match?
You can't return a reference to a locally allocated String
because the string is dropped when the function returns. There's no way to finagle your way around that. A &str
is simply a bad match for the type of data you want to return.
The most straightforward fix is to return an owned String
.
fn my_func(input: &str) -> String {
match input {
"a" => "Alpha".to_string(),
_ => format!("'{}'", "Quoted" ),
}
}
Another is to return a Cow <'_, str>
, which can hold either a borrowed or owned string depending on which you have. It's a bit fussy, but it does avoids unnecessary allocations. I only recommend this if efficiency is of utmost important; otherwise, just return String
.
fn my_func(input: &str) -> Cow<'_, str> {
match input {
"a" => "Alpha".into(),
_ => format!("'{}'", "Quoted" ).into(),
}
}
I'll also mention a third option -- for educational purposes, not for actual use, since it leaks memory. You can get a 'static
reference to an owned object if you leak it . Leaked memory is valid for the remainder of the program since it's never freed, and thus you can in fact get a reference to it.
// Warning: Do not use! Leaks memory.
fn my_func(input: &str) -> &'static str {
match input {
"a" => "Alpha",
_ => Box::leak(format!("'{}'", "Quoted").into_boxed_str()),
}
}
The problem is that the arm with format.().as_str()
produces an owned String
, as soon as your function returns, the String
is dropped and the &str
reference would become invalid.
You can use std::borrow::Cow
to allow a function to return both owned or borrowed strings.
In addition to the other answers, you can also change my_func
to take a parameter that tells it where to put its result instead of returning it:
use std::fmt::Write;
fn my_func(output: &mut impl Write, input: &str) {
match input {
"a" => write!(output, "Apha").unwrap(), // in fact, a &str from a crate
_ => write!(output, "'{}'", "Quoted" ).unwrap(),
};
}
fn main() {
let mut s = String::new();
my_func(&mut s, "a");
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.