如何从Vec检索移入结构的项目?

时间:2019-04-05 16:55:35

标签: rust borrow-checker

我有一个结构,其中包含结构的向量,例如

fn main() {
    let x: Vec<Item> = Vec::new(); 
    // assume x is filled with stuff
    do_things_with(x);
}

struct Item {
    value: String,
}

struct Context {
    x: Vec<Item>,
}

impl Context {
    fn get(&mut self, at: usize) -> Item {
        self.x[at]
    }
}

fn do_things_with(x: Vec<Item>) {
    let mut ctx = Context{
        x: x,
    };
    ctx.get(5);
}

我有一个Vec的东西,并将其传递给某个函数,该函数创建上下文并在该结构中存储传递的值。然后,我想查看此Vec中的项目,因此我有一些帮助功能,例如'get',它将在指定的索引处获取项目。

这似乎一切都很好,用C或任何语言都可以,但是Rust抱怨道:

'cannot move out of borrowed content'

对于“获取”功能,我们尝试在向量中访问该项目。

我在这里做什么错了?

1 个答案:

答案 0 :(得分:2)

这里的问题是Vec对其拥有的Item具有所有权,但是Context.get试图直接返回Item(并获得其所有权) )。

如果Context.get只需要让调用者窥视向量的内容,则应返回对Item的引用,而不是Item:

impl Context {
    fn get(&mut self, at: usize) -> &Item {
        &self.x[at]
    }
}

在上述情况下,Context.get可以对self进行不变的引用,因为它没有改变任何内容。此外,如果您想允许Context.get的调用者修改引用的项目,则将返回&mut Item而不是&Item

impl Context {
    fn get(&mut self, at: usize) -> &mut Item {
        &mut self.x[at]
    }
}

编辑:正如@a​​pemanzilla在评论中有帮助地指出的那样,如果希望Context.get在Clone处返回Item的单独副本,则还可以让Item实现at特性:

#[derive(Clone)]
struct Item {
    value: String,
}

impl Context {
    fn get(&mut self, at: usize) -> Item {
        self.x[at].clone()
    }

更改返回的项目不会修改self.x中包含的内容;这可能与您预期的不一样。