我有一个结构,其中包含结构的向量,例如
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'
对于“获取”功能,我们尝试在向量中访问该项目。
我在这里做什么错了?
答案 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]
}
}
编辑:正如@apemanzilla在评论中有帮助地指出的那样,如果希望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中包含的内容;这可能与您预期的不一样。