迭代器查找,暂时借用的临时值下降

时间:2017-06-18 10:47:30

标签: arrays iterator find rust

我有一个以常量形式定义的数组,在任何函数之外:

const VALUES: [(char, &str); 2] = [('A', "abc"), ('B', "acb")];

我尝试使用位于Iterator上的find()方法,以便根据谓词从数组中提取单个元素:

VALUES.iter().find(|&&(name, _)| name == 'A');

在这种形式下,它工作正常。但是,我无法将找到的元素评估为任何内容,因为我尝试创建let绑定时,尝试绑定结果,根据文档应该返回{{1} }。

让我们将第二行更改为不起作用的行:

Option<T>

Playground

根据文档,人们会期望这会返回const VALUES: [(char, &str); 2] = [('A', "abc"), ('B', "acb")]; fn main() { let result = VALUES.iter().find(|&&(name, _)| name == 'A'); } ,但我会收到编译错误:

Option<T>

我完全糊涂了;我确定我已经搞砸了#34;借用检查器&#34;。也许有人可以指出我正确的方向?

2 个答案:

答案 0 :(得分:2)

问题在于您将该数组转换为迭代器的具体方式。

首先,Rust中的const实际上并不存在于任何地方。相反,他们会在他们使用的任何地方替换价值。因此,每次使用常量时,您都会获得它的新副本。

其次,您正在使用IntoIterator::into_iter。这将主题按值并将其转换为迭代器。

这些与第三部分结合:IntoIterator 是针对固定大小的数组实现的。它仅针对指针实现为固定大小的数组。因此,为了调用into_iter,编译器必须插入一个自动借用的调用者。

那么,实际发生的是:

let t = {
    // Make a new copy of `VALUES`.
    let values: [(char, &str); 5] = VALUES;
    // Borrow it.
    let values: &[_] = &values;
    // Call `into_iter` on the borrow.
    IntoIterator::into_iter(values).find(|&&(name, _)| name == 'A')
};

这会导致问题,因为编译器必须同时复制借用VALUES才能获得迭代器。像所有临时工一样,复制品只能在声明中存在,但借用(通过绑定变量)必须比这更长寿。

最好的解决方案是将VALUES 指针添加到数组中。这可以防止复制整个阵列;相反,你只在每次使用时复制指针。

const VALUES: &[(char, &str)] = &[...];

或者,您可以明确制作VALUES的副本并将其存储在变量中,然后在上使用into_iter 。但是,和以前一样,这会引入不必要的复制。

答案 1 :(得分:0)

DK.'s answer是正确的,但我建议您进行更简单的更改以使代码正常工作 - 使用static代替const

来自documentation about static and const

  

更具体地说,Rust中的常量在内存中没有固定的地址。

  

静态项目在使用时不会内联。这意味着每个值只有一个实例,它位于内存中的固定位置。

切换到static可以获得正在迭代的内容的内存地址。

static VALUES: [(char, &str); 2] = [('A', "abc"), ('B', "acb")];

fn main() {
    let result = VALUES.iter().find(|&&(name, _)| name == 'A');
}

此处resultOption<&(char, &str)>