网上有很多教学,包括 rust course 里对引用生命周期的各种自动添加规则讲了很多,但是看起来总让人感觉云里雾里,感觉总是告诉你说某某情况会编译报错,但只知道会错,教学也并未提供一种推荐的解决方案,导致最终解决问题的时候要不然是无脑注释'a 让编译器过了,要不然就是到处 copy(),重复着低水平代码。
像以下描述一个最简场景
use std::collections::HashMap;
fn index_t_words(sentence: &String) -> HashMap<&str, usize> {
let mut result: HashMap<&str, usize> = HashMap::new();
for (idx, word) in sentence.split(' ').enumerate() {
if word.chars().nth(0).unwrap() == 't' {
result.insert(word, idx);
}
}; result
}
fn main() {
let sentence: String = String::from("magic happens in the test statement");
println!("{:?}", index_t_words(&sentence))
}
它实现一个非常简单的需求,输入字符串"magic happens in the test statement",查找其中以 t 开头的单词的位置(理论返回结果 {"the": 3, "test": 4}),上述代码编译器能通过,倒是没什么难理解的地方。但是如果再加入一个引用作为函数的参数,不参与任何逻辑执行,仅改变函数签名,此时按照经验编译器就会报错了,因为无法应用自动生命周期标注的规则,提示你需要人工解决。
实际生产中总是不可避免地出现这种情况,我们不可能总是保证函数或方法只有单一输入。
use std::collections::HashMap;
fn index_t_words(sentence: &String, bias: &str) -> HashMap<&str, usize> {
let mut result: HashMap<&str, usize> = HashMap::new();
for (idx, word) in sentence.split(' ').enumerate() {
if word.chars().nth(0).unwrap() == 't' {
result.insert(word, idx);
}
}; result
}
fn main() {
let sentence: String = String::from("magic happens in the test statement");
let bias = "spoiler";
println!("{:?}", index_t_words(&sentence, &bias))
}
此时如果给函数签名无脑全标'a 就又能编译通过,
fn index_t_words<'a>(sentence: &'a String, bias: &'a str) -> HashMap<&'a str, usize> {}
说实话看完 rust course 也搞不太清楚发生了什么,理论上标注和资源释放不发生任何联系,为什么这么手动标了一下编译器就过了?
以至于再进阶一种情况,如果需要返回的变量所有权在函数内部,比如下面这种情况,在生产中也不少见,有时不可避免地资源的所有权在被调用的函数内部产生。因为函数结束时要释放资源,引用当然是无法带到函数外面的,会报错可以理解,一般来说解决方案也是通过 copy 把所有权转移出去。但是如果我们需要面临输出到多个位置(比如函数签名不光输出一个 HashMap ,还有另一个 Vec ,也同样引用&str ),如果不想每输出到一个结构就新拷贝一份的话,应该采用什么样的解决方案呢?
fn index_t_words() -> HashMap<&str, usize> {
let sentence: String = String::from("magic happens in the test statement");
let mut result: HashMap<&str, usize> = HashMap::new();
for (idx, word) in sentence.split(' ').enumerate() {
if word.chars().nth(0).unwrap() == 't' {
result.insert(word, idx);
}
}; result
}
fn main() { println!("{:?}", index_t_words()) }
最后吐槽一下都说 rust 学习曲线比较陡峭,刚开始特别难,后面慢慢变简单。我个人体验上倒是感觉刚开始特别简单,越看感觉越难。。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.