如何通过获取可变变量的所有权来替换它的值? [英] How do you replace the value of a mutable variable by taking ownership of it?

查看:12
本文介绍了如何通过获取可变变量的所有权来替换它的值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 LinkedList,我想删除所有未通过测试的元素.但是,我遇到了错误cannot move out of borrowed content.

I am working with a LinkedList and I want to remove all elements which do not pass a test. However, I am running into the error cannot move out of borrowed content.

据我了解,这是因为我正在使用 &mut self,所以我无权使包含的值之一无效(即移动),即使是片刻构造一个新的值列表.

From what I understand, this is because I am working with &mut self, so I do not have the right to invalidate (i.e. move) one of the contained values even for a moment to construct a new list of its values.

在 C++/Java 中,我会简单地迭代列表并删除任何符合条件的元素.由于我还没有找到删除,我将其解释为迭代、过滤和收集.

In C++/Java, I would simply iterate the list and remove any elements which match a criteria. As there is no remove that I have yet found, I have interpreted it as an iterate, filter, and collect.

目标是避免创建临时列表、克隆值以及需要获取 self 并返回新"对象.我构建了一个产生相同错误的示例.游乐场.

The goal is to avoid creating a temporary list, cloning values, and needing take self and return a "new" object. I have constructed an example which produces the same error. 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);
}

在我的实际情况中,我不能简单地使用包装对象,因为它需要从不同的地方引用并包含其他重要值.

In my actual case, I cannot simply consume the wrapping object because it needs to be referenced from different places and contains other important values.

在我的研究中,我发现了一些不安全代码,这让我怀疑是否可以构造一个安全函数来执行此操作类似于 std::mem::替换.

In my research, I found some 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.不知道有多贵.

You can std::mem::swap your field with a temp, and then replace it with your modified list like this. The big downside is the creation of the new LinkedList. I don't know how expensive that is.

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();
}

这篇关于如何通过获取可变变量的所有权来替换它的值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆