我只花了一个星期阅读Rust Book,现在我正在开发我的第一个程序,它将文件路径返回到系统壁纸:
pub fn get_wallpaper() -> &str {
let output = Command::new("gsettings");
// irrelevant code
if let Ok(message) = String::from_utf8(output.stdout) {
return message;
} else {
return "";
}
}
我收到错误expected lifetime parameter on &str
,我知道Rust想要一个输入&str
,它将作为输出返回,因为我在函数内创建的任何&str
都会立即清除功能结束后。
我知道我可以通过返回String
而不是&str
来回避这个问题,并且对类似问题的许多回答都说了很多。但我似乎也可以这样做:
fn main() {
println!("message: {}", hello_string(""));
}
fn hello_string(x: &str) -> &str {
return "hello world";
}
从我的功能中获取&str
。有人可以向我解释为什么这很糟糕,为什么我不应该这样做?或者也许它在某些情况下并不坏并且没问题?
答案 0 :(得分:22)
你cannot return a &str
if you've allocated the String
in the function。关于why的进一步讨论,以及它not limited to strings的事实。这使您的选择更容易 :返回String
。
String
是堆分配的,并且构建为可变的。
String
是堆分配的,因为它们的长度未知。由于该分配仅由String
拥有,因此授予变异字符串的能力。
我的函数只返回一个文件路径以供参考,我宁愿把它留给调用者来决定他们是否需要堆存储的可变字符串。
这是不可能的。您的功能已执行分配。如果您不将分配返回给调用者,则必须取消分配该值以防止内存泄漏。如果在重新分配后返回,那将是无效的引用,导致内存安全违规。
但我似乎也可以这样做:
fn hello_string(x: &str) -> &str { return "hello world"; }
从我的功能中获取
&str
。有人可以向我解释为什么会这样 是坏的,为什么我永远不应该这样做?或者也许它不坏也没关系 某些情况?
它不是坏,它实际上并不能让你在原始案例中做你想做的事情。 "hello world"
是&'static str
,是一个字符串切片,存储在程序本身的代码中。它具有固定长度,并且已知寿命超过main
。
签名fn hello_string(x: &str) -> &str
可以扩展为fn hello_string<'a>(x: &'a str) -> &'a str
。这表示生成的字符串切片必须与输入字符串具有相同的生存期。静态字符串将比任何生命周期更长,因此可以替换。
这对于结果仅基于输入字符串的函数非常有用:
fn long_string(x: &str) -> &str {
if x.len() > 10 {
"too long"
} else {
x
}
}
但是,在您的情况下,该函数拥有String
。如果您尝试返回对String
的引用,则与输入字符串完全无关:
fn hello_string(x: &str) -> &str {
&String::from("hello world")
}
你会遇到常见的错误消息&#34;借来的价值不够活跃&#34;。这是因为借用的值只存在于方法结束之前,而不是输入字符串切片。你不能欺骗&#34;编译器(如果可以的话,这是一个主要的错误)。