替换结构字段时“无法移出借来的内容”[重复]

问题描述 投票:0回答:2

这个问题在这里已有答案:

考虑这个例子:

struct Item {
    x: u32,
}

impl Item {
    pub fn increment(self, amount: u32) -> Self {
        Item { x: self.x + amount }
    }
}

struct Container {
    item: Item,
}

impl Container {
    pub fn increment_item(&mut self, amount: u32) {
        // This line causes "cannot move out of borrowed content"
        self.item = self.item.increment(amount);
    }
}

如您所见,Item.increment使用该项并返回一个新实例。

Container.increment_item中我想用Item.increment返回的那个替换当前项目,但编译器用cannot move out of borrowed content错误向我大喊大叫。

Container.increment_item selfmut所以我可以改变它的字段,我不明白为什么编译器不允许我这样做。

我知道我可以让Container.increment_item消耗self并返回一个新的对象,就像Item.increment一样,并且它可以工作,但我想知道为什么我得到错误,我怎么能解决它,当我真的不能消耗容器。

rust borrow-checker
2个回答
1
投票
  • Item::increment按价值预期self,它移动被调用的Item
  • Container::increment_item通过引用获取&mut self,它允许你改变self,但它不允许你拥有self(或其任何部分)的所有权。
  • 当您调用self.item.increment(amount)时,您试图按值传递self.item,从而将所有权移至Item::increment函数,但不允许您通过引用您不拥有的值来执行此操作。

只需通过可变引用将self传递给Item::increment,这正是可变引用的用途:

struct Item {
    x: u32,
}

impl Item {
    pub fn increment(&mut self, amount: u32) {
        self.x += amount;
    }
}

struct Container {
    item: Item,
}

impl Container {
    pub fn increment_item(&mut self, amount: u32) {
        self.item.increment(amount);
    }
}

如果你坚持取得Item的所有权,那么你可以使用mem::replace

use std::mem;

struct Item {
    x: u32,
}

impl Item {
    pub fn increment(self, amount: u32) -> Self {
        Item { x: self.x + amount }
    }
}

struct Container {
    item: Item,
}

impl Container {
    pub fn increment_item(&mut self, amount: u32) {
        self.item = mem::replace(&mut self.item, Item { x: 0 }).increment(amount);
    }
}

但在这种情况下似乎不必要地复杂化。


-1
投票

increment_item()通过引用获取Container并且item不能被移动(或“消耗”),因为increment()Item为值,它位于引用之后。解决这个问题的最快方法是使Item成为Copy类型。这将触发副本而不是移动(即消耗)。 playground

#[derive(Clone, Copy)]
struct Item {
    x: u32,
}

有关更多信息,请参阅Copy

© www.soinside.com 2019 - 2024. All rights reserved.