无法 return 字符串切片向量:借用的值寿命不够长
Unable to return a vector of string slices: borrowed value does not live long enough
我是 Rust 的新手,我在使用借用检查器时遇到了一些问题。我不明白为什么这段代码无法编译。抱歉,如果这与之前回答的问题很接近,但我似乎无法在我看过的其他问题中找到解决方案。
我理解与 的相似之处,但在那种情况下,它只是一个被 return 编辑的字符串,不足以让我用我试图 [=30] 的代码进行推理=] 一个向量。据我了解,我正在尝试 return 对 str
类型的引用,这些类型将在功能块末尾超出范围,因此我应该将 &str
的向量映射到String
的向量?我不太关心将 &str
转换为 String
的性能影响。首先,我想让它正常工作。
这是代码,错误在lex
函数中。
use std::io::prelude::*;
use std::fs::File;
use std::env;
fn open(mut s: &mut String, filename: &String) {
let mut f = match File::open(&filename) {
Err(_) => panic!("Couldn't open file"),
Ok(file) => file,
};
match f.read_to_string(&mut s) {
Err(_) => panic!("Couldn't read file"),
Ok(_) => println!("File read successfully"),
};
}
fn lex(s: &String) -> Vec<&str> {
let token_string: String = s.replace("(", " ( ")
.replace(")", " ) ");
let token_list: Vec<&str> = token_string.split_whitespace()
.collect();
token_list
}
fn main() {
let args: Vec<_> = env::args().collect();
if args.len() < 2 {
panic!("Please provide a filename");
} else {
let ref filename = args[1];
let mut s = String::new();
open(&mut s, filename);
let token_list: Vec<&str> = lex(&s);
println!("{:?}", token_list);
}
}
这是错误信息
error: borrowed value does not live long enough
self.0.borrow().values.get(idx)
^~~~~~~~~~~~~~~
reference must be valid for the anonymous lifetime #1 defined on the block at 23:54...
pub fn value(&self, idx: usize) -> Option<&Value> {
^
note: ...but borrowed value is only valid for the block at 23:54
pub fn value(&self, idx: usize) -> Option<&Value> {
^
我发现很难用这段代码推理,因为以我对 Rust 的经验水平,我无法想象这些变量的生命周期。任何帮助将不胜感激,因为我花了一两个小时试图解决这个问题。
问题是您在 lex
函数中分配一个新的 String
(token_string
),然后 return 对它的引用数组,但是 token_string
一旦在函数结束时超出范围,就会被删除(并释放内存)。
fn lex(s: &String) -> Vec<&str> {
let token_string: String = s.replace("(", " ( ") // <-- new String allocated
.replace(")", " ) ");
let token_list: Vec<&str> = token_string.split_whitespace()
.collect();
token_list // <-- this is just an array of wide pointers into token_string
} // <-- token_string gets freed here, so the returned pointers
// would be pointing to memory that's already been dropped!
有几种方法可以解决这个问题。一种是强制 lex
的调用者传入要用于收集的缓冲区。这会将签名更改为 fn lex<'a>(input: &String, buffer: &'a mut String) -> Vec<&'a str>
此签名将指定 returned &str
的生命周期至少与传入的缓冲区的生命周期一样长。
另一种方法是 return 一个 Vec<String>
而不是 Vec<&str>
如果你能容忍额外的分配。
我是 Rust 的新手,我在使用借用检查器时遇到了一些问题。我不明白为什么这段代码无法编译。抱歉,如果这与之前回答的问题很接近,但我似乎无法在我看过的其他问题中找到解决方案。
我理解与 str
类型的引用,这些类型将在功能块末尾超出范围,因此我应该将 &str
的向量映射到String
的向量?我不太关心将 &str
转换为 String
的性能影响。首先,我想让它正常工作。
这是代码,错误在lex
函数中。
use std::io::prelude::*;
use std::fs::File;
use std::env;
fn open(mut s: &mut String, filename: &String) {
let mut f = match File::open(&filename) {
Err(_) => panic!("Couldn't open file"),
Ok(file) => file,
};
match f.read_to_string(&mut s) {
Err(_) => panic!("Couldn't read file"),
Ok(_) => println!("File read successfully"),
};
}
fn lex(s: &String) -> Vec<&str> {
let token_string: String = s.replace("(", " ( ")
.replace(")", " ) ");
let token_list: Vec<&str> = token_string.split_whitespace()
.collect();
token_list
}
fn main() {
let args: Vec<_> = env::args().collect();
if args.len() < 2 {
panic!("Please provide a filename");
} else {
let ref filename = args[1];
let mut s = String::new();
open(&mut s, filename);
let token_list: Vec<&str> = lex(&s);
println!("{:?}", token_list);
}
}
这是错误信息
error: borrowed value does not live long enough
self.0.borrow().values.get(idx)
^~~~~~~~~~~~~~~
reference must be valid for the anonymous lifetime #1 defined on the block at 23:54...
pub fn value(&self, idx: usize) -> Option<&Value> {
^
note: ...but borrowed value is only valid for the block at 23:54
pub fn value(&self, idx: usize) -> Option<&Value> {
^
我发现很难用这段代码推理,因为以我对 Rust 的经验水平,我无法想象这些变量的生命周期。任何帮助将不胜感激,因为我花了一两个小时试图解决这个问题。
问题是您在 lex
函数中分配一个新的 String
(token_string
),然后 return 对它的引用数组,但是 token_string
一旦在函数结束时超出范围,就会被删除(并释放内存)。
fn lex(s: &String) -> Vec<&str> {
let token_string: String = s.replace("(", " ( ") // <-- new String allocated
.replace(")", " ) ");
let token_list: Vec<&str> = token_string.split_whitespace()
.collect();
token_list // <-- this is just an array of wide pointers into token_string
} // <-- token_string gets freed here, so the returned pointers
// would be pointing to memory that's already been dropped!
有几种方法可以解决这个问题。一种是强制 lex
的调用者传入要用于收集的缓冲区。这会将签名更改为 fn lex<'a>(input: &String, buffer: &'a mut String) -> Vec<&'a str>
此签名将指定 returned &str
的生命周期至少与传入的缓冲区的生命周期一样长。
另一种方法是 return 一个 Vec<String>
而不是 Vec<&str>
如果你能容忍额外的分配。