gpt4 book ai didi

rust - 与(表面上)看起来非常安全的短暂生命周期值混淆

转载 作者:行者123 更新时间:2023-11-29 08:04:14 24 4
gpt4 key购买 nike

我在用 Rust 编写词法分析器时遇到问题,其中某些函数开始提示简单的片段,否则这些片段看起来无害。这开始变得令人烦恼,因为错误消息无法帮助我查明问题的原因,所以这是我第二次在同一周内联系同一程序(上一个问题 here)。

我读过这本书,我已经了解了我能从中了解的一切。我还观看/阅读了许多其他讨论生命周期(显式和隐式)的文章和视频,并且在大多数情况下,借用和移动背后的概念非常有意义,但以下情况除外:

我的词法分析器有一个 next 函数,它的目的是向前看下一个字符并返回它。

struct Lexer<'a> {
src: str::Chars<'a>,
buf: String,
// ... not important
}

impl<'a> Lexer<'a> {
// ... not relevant

// originally this -> Option<&char> which caused it's own slew of problems
// that I thought dereferencing the character would solve.
fn next(&self) -> Option<char> {
let res = self.src.peekable().peek();
// convert Option<&char> to Option<char>
match res {
Some(ref c) => Some(*c.clone()),
None => None
}
}

// ... not relevant
}

我在执行此操作时遇到的错误是:

error: borrowed value does not live long enough
let res = self.src.peekable().peek();
^~~~~~~~~~~~~~~~~~~

我从这个错误中了解到,peekable() 的值生命周期不够长,这对我来说很有意义。我只是在该行中引用 return 并调用另一个函数,我想它会使用迭代器返回指向下一个位置的字符的指针。我天真的解决方案是:

let mut peeker = self.src.peekable();
let res = peeker.peek();

如果我实现这个解决方案,我会看到一个不同的错误,这对我来说也没有意义:

error: cannot move out of borrowed content
let mut peeker = self.src.peekable();
^~~~

我不太确定是什么将 self 从借用的上下文中移出(我知道它是从 &self 中借用的,但不确定是什么将它从借用的上下文中移出.

编辑

我提出了一个问题,其中的细节非常不准确。帖子中包含这些详细信息的部分已根据实际情况进行了更新 - 我将遇到类似错误的两种不同情况混为一谈(至少与我相似)。

最佳答案

让我们从第二个错误开始。

如评论中所述,Iterator::peekable 是一个迭代器适配器,消耗 它将使其可窥视的迭代器。一个小复制品:

let values = [1,2,3];
let mut iterator = values.iter();
iterator.peekable(); // Consumes `iterator`
iterator.next(); // Not available anymore!

您可以使用 Iterator::by_ref 来获取一个引用,该引用本身可以被使用。请注意,底层迭代器仍将被推进!

let values = [1,2,3];
let mut iterator = values.iter();
iterator.by_ref().peekable();
iterator.next();

在您的情况下,您正在尝试使用借用结构的值(通过 &self),它具有特定错误 cannot move out of borrowed content


让我们看看您的原始错误:

let values = [1,2,3];
let next = values.iter().peekable().peek();

这里的问题是 peek 返回一个 reference。这是有道理的,因为我们不知道我们正在迭代的项目是否可以Copy。但是,该引用必须有一个地方可以住。这个地方就是 Peekable 迭代器本身! Peekable 分配足够的空间来存储“下一个”元素。当您调用 peek 时,它会推进底层迭代器,存储值,然后返回引用。查看 peek 的函数签名以查看在代码中捕获的内容:

fn peek(&mut self) -> Option<&I::Item>

您可以重新添加明确的生命周期:

fn peek<'a>(&'a mut self) -> Option<&'a I::Item>

在单行版本中,您创建然后销毁 Peekable,因此值无处可存,因此引用在同一语句中消失。

关于rust - 与(表面上)看起来非常安全的短暂生命周期值混淆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29805958/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com