我有一个带函数的结构remove
,并且我希望remove
函数在实际删除时返回新实例或相同的引用
但我Cannot move
尝试的时候return *self
是否可以?
从错误来看我不这么认为,但是怎么Cow
可能呢?
代码:
use std::collections::HashMap;
#[derive(Clone)]
struct Something {
data: HashMap<char, u16>,
}
impl Something {
fn new() -> Self {
return Something {
data: HashMap::new()
}
}
fn get(&self, c: char) -> Option<&u16> {
return self.data.get(&c);
}
fn add(&self, c: char, value: u16) -> Self {
let mut n = self.clone();
n.data.insert(c, value);
return n;
}
fn remove(&self, c: char) -> Self {
if !self.data.contains_key(&c) {
return *self; // <-- error[E0507]: cannot move out of `*self` which is behind a shared reference
}
let mut n = self.clone();
n.data.remove(&c);
return n;
}
}
fn main() {
let s = Something::new();
let s = s.add('a', 1);
let s = s.add('b', 2);
let s = s.remove('a');
// Should return the same instance as c is missing
let s = s.remove('c');
}
但是如果我将remove
函数改为返回&Self
,那么我就无法返回对函数中声明的变量的引用:
fn remove(&self, c: char) -> &Self {
if !self.data.contains_key(&c) {
return self;
}
let mut n = self.clone();
n.data.remove(&c);
return &n; // <--- error[E0515]: cannot return reference to local variable `n`
}
我知道我可以避免借用something
但我不想转移所有权:
// <--- self and not &self
fn remove(self, c: char) -> Self {
if !self.data.contains_key(&c) {
return self;
}
let mut n = self.clone();
n.data.remove(&c);
return n;
}
因为接下来的操作将会失败:
fn main() {
let s = Something::new();
let s = s.add('a', 1);
let s = s.add('b', 2);
let s1 = s.remove('a');
let s2 = s.remove('a'); // <-- error[E0382]: use of moved value: `s`
}
-
&self
>Self
方法总是需要克隆。这是所有权的基本原则。除了显而易见的“仅克隆”之外,还有两种可能的解决方案:
使其成为
&self
->&self
。当然,那么你将无法修改它,但Cow
可以解决这个问题:使用廉价的可克隆数据结构,该结构也允许写时复制,例如
Rc
或Arc
: