无法返回字符串切片的向量:借来的值不够长

时间:2016-08-10 08:32:41

标签: vector rust borrowing

我是Rust的新手,我在借阅检查器方面遇到了一些麻烦。我不明白为什么这段代码不会编译。很抱歉,如果这与以前回答的问题很接近,但我似乎无法在我看过的其他问题中找到解决方案。

我理解与Return local String as a slice (&str)的相似之处,但在这种情况下,它只返回一个字符串,并且不足以让我用我的代码推理我试图返回一个向量。根据我的理解,我试图返回对str类型的引用,这些类型将超出功能块末尾的范围,因此我应该将&str的向量映射到{的向量中{1}}?我并不关心将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);
    }
}

我发现很难用这个代码推理,因为凭借我对Rust的经验,我无法看到这些变量的生命周期。任何帮助都会受到赞赏,因为我花了一两个小时试图解决这个问题。

1 个答案:

答案 0 :(得分:2)

问题是您在String函数内部分配了新的token_stringlex),然后返回了对它的引用数组,但是{{1}一旦它超出函数末尾的范围,就会被删除(并释放内存)。

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>的生命周期至少与传入的缓冲区的生命周期一样长。

另一种方法是,如果您可以容忍额外的分配,则只返回&str而不是Vec<String>