“不能用向量移出dereference`&`-pointer”

时间:2014-11-24 04:02:46

标签: rust

我现在正在尝试使用Rust,而且我真的被各种各样的随机编译器错误所困扰:

error: cannot move out of dereference of `&`-pointer
    return list[idx];
           ^~~~~~~~~

有问题的片段转载如下。 list是一个单词列表,其思路是从列表中返回一个在一定长度内(minLength和maxLength之间)的随机单词。因此,我生成一个随机uint并使用模数将其约束到列表的大小。然后我想检查一下这个单词是否正确,如果它返回它。

显然,这不是最有效的方法,但我只是想要一些能够满足练习需要的简单方法。

fn get_a_word(list: Vec<String>, minLength: uint, maxLength: uint) -> String {
    loop {
        let idx = rand::random::<uint>() % list.len();
        if list[idx].len() > minLength && list[idx].len() < maxLength {
            return list[idx];
        }
    }
}

我已经对此错误消息的含义进行了一些调查,但是每个人似乎都会说,当您处理Option<T>次撤消时,这种情况就会出现,而不是试图从集合中获取价值。< / p>

这可能是一个非常简单的问题,但为什么地球上没有Rust只让你从集合/矢量/数组中返回一个值?

2 个答案:

答案 0 :(得分:3)

一次只能有一件东西可以拥有一个对象,而你在那里尝试做的事情会破坏那个不变量,因为你将在向量和返回位置返回字符串。对于方法Index::indexlist[idx]或多或少地扩展到*list.index(idx)(事实上,它比Index::indexIndexMut::index_mut更复杂一点。根据上下文确定,&list[idx]只是list.index(idx)的{​​{1}}和list[idx].method()的{​​{1}} - &self将是method。< / p>

你有几个选择;这里有三个:

  • 从列表中删除该值,并将其返回。你所拥有的list.index(idx).method()的其余部分将被删除,因此除了正确的Vec<String>之外的所有String最终都将被释放。

    return list.swap_remove(idx).unwrap();(比较swap_removeremove,前者更有效但改变了在这种情况下完全正常的顺序)代替return list[idx];会做的此

  • 克隆字符串。效率较低,但可以认为是可接受的。

    return list[idx].clone();会为此做。

  • 在整个事情中使用切片和参考:这是最有效的方式,通常是最惯用的方式。它是有效的,因为它不涉及任何分配或解除分配或移动大值。

    fn get_a_word(list: &[String], min_length: uint, max_length: uint) -> &str {
        loop {
            let idx = rand::random::<uint>() % list.len();
            if list[idx].len() > min_length && list[idx].len() < max_length {
                return list[idx].as_slice();
            }
        }
    }
    

答案 1 :(得分:2)

list[idx]*list.index(&idx)的简写。 index()在被索引的值内返回一个借来的指针(这里是Vec)。您不能通过取消引用借来的指针来移动值(此处为String);这就像拥有字符串的String中的“{1}}”。 Vec拥有堆上的分配;我们不能有两个引用相同堆分配的String值,或者它们都会在删除时尝试释放它,这将导致双重释放。

由于函数通过值接收String,这意味着Vec被移入函数中,因此函数可以随心所欲地执行它,因为它“拥有”{ {1}}(当函数退出时,Vec将被销毁)。例如,我们可以删除我们要从Vec返回的Vec,以便String不再拥有该Vec的所有权。

Vec

如果你不想在String退出时销毁fn get_a_word(mut list: Vec<String>, minLength: uint, maxLength: uint) -> String { loop { let idx = rand::random::<uint>() % list.len(); if list[idx].len() > minLength && list[idx].len() < maxLength { return list.remove(idx).unwrap(); } } } ,那么该函数应该会收到一个借用指向Vec的指针。如果我们这样做,函数可以简单地返回一个字符串切片。

get_a_word

如果必须绝对返回Vec,则可以克隆该值:

fn get_a_word(list: &Vec<String>, minLength: uint, maxLength: uint) -> &str {
    loop {
        let idx = rand::random::<uint>() % list.len();
        if list[idx].len() > minLength && list[idx].len() < maxLength {
            return list[idx].as_slice();
        }
    }
}