如何从字符串 _and_ 创建迭代器并将其存储在结构中?

问题描述

我正在尝试为我的结构创建一个构造函数,它将存储一个迭代器,String文件中读取。问题是一旦函数返回,String 就会被删除,编译器会抱怨 new() returns a value referencing data owned by the current function。有没有办法以某种方式将 String 与结构相关联,使其在返回后不会被删除

我想我理解这里的抱怨,但我不明白如何处理它,因为我希望构造函数同时处理文件读取和迭代器创建。

pub struct CharStream<'a> {
    input: std::str::Chars<'a>,filename: String,}
impl<'a> CharStream<'a> {
    pub fn new(filename: String) -> CharStream<'a> {
        let mut file = File::open(&filename).unwrap();
        let mut input = String::new();
        file.read_to_string(&mut input);
        CharStream {
            input: input.chars(),// Create an iterator over `input`
            filename: filename,}
        // `input` is dropped here
    }
}

解决方法

我会将 CharStream 重命名为 FileContents 并让它拥有文件的 filenamecontents 作为 String。然后,当您需要生成一个 TokenIter 来迭代 char 中的 contents 块时,您可以按需创建 Chars<'a> 并将其传递给 {{1 }} 然后。完整示例:

TokenIter

playground

,

String::chars() 返回的迭代器仅在原始字符串 input 存在时才有效。 inputnew 的末尾被删除,因此无法从函数中返回迭代器。

为了解决这个问题,您还想将 input 字符串存储在结构中,但随后您遇到了其他问题,因为一个结构成员不能引用同一结构的另一个成员.原因之一是结构体将变得不可移动,因为移动它会使引用无效。

最简单的解决方案可能是将 char 收集到 Vec<char> 中并将该向量存储在 CharStream 中。然后添加一个 usize 索引并编写您自己的 Iterator<Item = char> 实现。

另一种方法(更节省内存)是存储 String 本身,并按需创建 Chars 迭代器,但这当然会导致不同的 API。

涉及 RefCell 或类似包装器的解决方案也是可能的。