如何通过获取可变变量的所有权来替换它的值?
How do you replace the value of a mutable variable by taking ownership of it?
我正在使用 LinkedList
,我想删除所有未通过测试的元素。但是,我运行进入错误cannot move out of borrowed content
。
据我了解,这是因为我正在使用 &mut self
,所以我无权使其中一个包含的值无效(即移动),即使是暂时构建新列表它的价值。
在 C++/Java 中,我将简单地迭代列表并删除任何符合条件的元素。由于我还没有找到删除,我将其解释为迭代、过滤和收集。
目标是避免创建临时列表、克隆值以及需要 self
和 return 一个 "new" 对象。我构建了一个产生相同错误的示例。 Playground.
use std::collections::LinkedList;
#[derive(Debug)]
struct Example {
list: LinkedList<i8>,
// Other stuff here
}
impl Example {
pub fn default() -> Example {
let mut list = LinkedList::new();
list.push_back(-5);
list.push_back(3);
list.push_back(-1);
list.push_back(6);
Example { list }
}
// Simmilar idea, but with creating a new list
pub fn get_positive(&self) -> LinkedList<i8> {
self.list.iter()
.filter(|&&x| x > 0)
.map(|x| x.clone())
.collect()
}
// Now, attempt to filter the elements without cloning anything
pub fn remove_negative(&mut self) {
self.list = self.list.into_iter()
.filter(|&x| x > 0)
.collect()
}
}
fn main() {
let mut e = Example::default();
println!("{:?}", e.get_positive());
println!("{:?}", e);
}
在我的实际情况下,我不能简单地使用包装对象,因为它需要从不同的地方引用并且包含其他重要值。
在我的研究中,我发现了一些 unsafe code which leads me to question if a safe function could be constructed to perform this action in a similar way to std::mem::replace
。
您可以 std::mem::swap
使用临时字段,然后将其替换为修改后的列表,如下所示。最大的缺点是创建了新的 LinkedList。不知道有多贵
pub fn remove_negative(&mut self) {
let mut temp = LinkedList::new();
std::mem::swap(&mut temp, &mut self.list);
self.list = temp.into_iter()
.filter(|&x| x > 0)
.collect();
}
如果目标不是克隆,您可以使用引用计数指针:Rc 上的克隆方法会增加引用计数器。
use std::collections::LinkedList;
use std::rc::Rc;
#[derive(Debug)]
struct Example {
list: LinkedList<Rc<i8>>,
// ...
}
impl Example {
pub fn default() -> Example {
let mut list = LinkedList::new();
list.push_back(Rc::new(-5));
list.push_back(Rc::new(3));
list.push_back(Rc::new(-1));
list.push_back(Rc::new(6));
Example { list }
}
// Simmilar idea, but with creating a new list
pub fn get_positive(&self) -> LinkedList<Rc<i8>> {
self.list.iter()
.filter(|&x| x.as_ref() > &0)
.map(|x| x.clone())
.collect()
}
// Now, attempt to filter the elements without cloning anything
pub fn remove_negative(&mut self) {
self.list = self.list.iter()
.filter(|&x| x.as_ref() > &0)
.map(|x| x.clone())
.collect()
}
}
fn main() {
let mut e = Example::default();
e.remove_negative();
println!("{:?}", e.get_positive());
println!("{:?}", e);
}
我正在使用 LinkedList
,我想删除所有未通过测试的元素。但是,我运行进入错误cannot move out of borrowed content
。
据我了解,这是因为我正在使用 &mut self
,所以我无权使其中一个包含的值无效(即移动),即使是暂时构建新列表它的价值。
在 C++/Java 中,我将简单地迭代列表并删除任何符合条件的元素。由于我还没有找到删除,我将其解释为迭代、过滤和收集。
目标是避免创建临时列表、克隆值以及需要 self
和 return 一个 "new" 对象。我构建了一个产生相同错误的示例。 Playground.
use std::collections::LinkedList;
#[derive(Debug)]
struct Example {
list: LinkedList<i8>,
// Other stuff here
}
impl Example {
pub fn default() -> Example {
let mut list = LinkedList::new();
list.push_back(-5);
list.push_back(3);
list.push_back(-1);
list.push_back(6);
Example { list }
}
// Simmilar idea, but with creating a new list
pub fn get_positive(&self) -> LinkedList<i8> {
self.list.iter()
.filter(|&&x| x > 0)
.map(|x| x.clone())
.collect()
}
// Now, attempt to filter the elements without cloning anything
pub fn remove_negative(&mut self) {
self.list = self.list.into_iter()
.filter(|&x| x > 0)
.collect()
}
}
fn main() {
let mut e = Example::default();
println!("{:?}", e.get_positive());
println!("{:?}", e);
}
在我的实际情况下,我不能简单地使用包装对象,因为它需要从不同的地方引用并且包含其他重要值。
在我的研究中,我发现了一些 unsafe code which leads me to question if a safe function could be constructed to perform this action in a similar way to std::mem::replace
。
您可以 std::mem::swap
使用临时字段,然后将其替换为修改后的列表,如下所示。最大的缺点是创建了新的 LinkedList。不知道有多贵
pub fn remove_negative(&mut self) {
let mut temp = LinkedList::new();
std::mem::swap(&mut temp, &mut self.list);
self.list = temp.into_iter()
.filter(|&x| x > 0)
.collect();
}
如果目标不是克隆,您可以使用引用计数指针:Rc 上的克隆方法会增加引用计数器。
use std::collections::LinkedList;
use std::rc::Rc;
#[derive(Debug)]
struct Example {
list: LinkedList<Rc<i8>>,
// ...
}
impl Example {
pub fn default() -> Example {
let mut list = LinkedList::new();
list.push_back(Rc::new(-5));
list.push_back(Rc::new(3));
list.push_back(Rc::new(-1));
list.push_back(Rc::new(6));
Example { list }
}
// Simmilar idea, but with creating a new list
pub fn get_positive(&self) -> LinkedList<Rc<i8>> {
self.list.iter()
.filter(|&x| x.as_ref() > &0)
.map(|x| x.clone())
.collect()
}
// Now, attempt to filter the elements without cloning anything
pub fn remove_negative(&mut self) {
self.list = self.list.iter()
.filter(|&x| x.as_ref() > &0)
.map(|x| x.clone())
.collect()
}
}
fn main() {
let mut e = Example::default();
e.remove_negative();
println!("{:?}", e.get_positive());
println!("{:?}", e);
}