我只花了一个星期阅读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 "";
}
}
Run Code Online (Sandbox Code Playgroud)
我收到错误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";
}
Run Code Online (Sandbox Code Playgroud)
得到&str我的功能.有人可以向我解释为什么这很糟糕,为什么我不应该这样做?或者也许它在某些情况下并不坏并且没问题?
She*_*ter 26
你不能返回&str,如果你已经分配String的功能.还有进一步的讨论为什么,以及它不仅限于字符串的事实.这使您的选择更容易:返回String.
Strings是堆分配的,并且构建为可变的.
Strings是堆分配的,因为它们具有未知长度.由于该分配完全由该分配String,因此授予变异字符串的能力.
我的函数只返回一个文件路径以供参考,我宁愿把它留给调用者来决定他们是否需要堆存储的可变字符串.
这是不可能的.您的功能已执行分配.如果不将分配返回给调用者,则必须取消分配该值以防止内存泄漏.如果在重新分配后返回,那将是无效的引用,导致内存安全违规.
但我似乎也可以这样做:
Run Code Online (Sandbox Code Playgroud)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
}
}
Run Code Online (Sandbox Code Playgroud)
但是,在您的情况下,该函数拥有String.如果您尝试返回String对输入字符串完全无关的a的引用:
fn hello_string(x: &str) -> &str {
&String::from("hello world")
}
Run Code Online (Sandbox Code Playgroud)
你会遇到常见的错误信息"借来的价值不够长".这是因为借用的值只存在于方法结束之前,而不是输入字符串切片.你不能"欺骗"编译器(或者你可以,这是一个主要的错误).