我想改变Outer struct ,在它的实现之外使用它自己,而不复制它的属性.如何在Rust中正确实现它?有没有一种简单的方法可以同时拥有可变和不可变的引用?

下面是代码示例(也许这有点牵强,但它很好地说明了我面临的问题):

use std::sync::Mutex;

#[derive(Debug)]
struct Inner {
    n: i64,
    factor: i64,
}

#[derive(Debug)]
struct Max {
    v: i64
}

#[derive(Debug)]
struct Outer {
    inners: Vec<Inner>,
    max: Max,
}

fn main() {
    let mutex_s = Mutex::new(Outer {
        inners: vec![
            Inner { n: 1, factor: 2 },
            Inner { n: 2, factor: 2 },
            Inner { n: 3, factor: 3 },
            Inner { n: 4, factor: 3 },
        ],
        max: Max { v: 5 },
    });

    let mut s = mutex_s.lock().unwrap();
    
    s.inners.retain(|i| i.n * i.factor < s.max.v);

    println!("{:?}", s);
}

在这里,我得到以下错误:cannot borrow 's' as immutable because it is also borrowed as mutable.

我想这里我需要内部可变性,但我不确定如何正确、优化和有效地实现它.

推荐答案

如果你需要同时访问innersmax,你需要它们在不同的Mutex中,Mutex应该是around the current type of inners, (in your example max is only accessed immutably so it doesn't need a Mutex) not around the whole Outer struct.换句话说:对于需要同时访问的every字段,您需要一个different Mutex,这里只有inners个成员:

#[derive(Debug)]
struct Outer {
    inners: Mutex<Vec<Inner>>,
    max: Max,
}

fn main() {
    let s = Outer {
        inners: Mutex::new(vec![
            Inner { n: 1, factor: 2 },
            Inner { n: 2, factor: 2 },
            Inner { n: 3, factor: 3 },
            Inner { n: 4, factor: 3 },
        ]),
        max: Max { v: 5 },
    };
    
    s.inners.lock().unwrap().retain(|i| i.n * i.factor < s.max.v);

    println!("{:?}", s);
}

或者,如果字段对您可见(它们是pubOuter是本地类型),则可以拆分borrow :

fn main() {
    let mutex_s = Mutex::new(Outer {
        inners: vec![
            Inner { n: 1, factor: 2 },
            Inner { n: 2, factor: 2 },
            Inner { n: 3, factor: 3 },
            Inner { n: 4, factor: 3 },
        ],
        max: Max { v: 5 },
    });

    let mut s = mutex_s.lock().unwrap();

    // splitting the borrow into `inners` and `max` so only `max` is captured in the closure.
    let Outer { inners, max } = &mut *s;

    // or for more control over the mutability:
    let Outer {
        ref mut inners,
        ref max,
    } = *s;

    inners.retain(|i| i.n * i.factor < max.v);

    println!("{:?}", s);
}

Rust相关问答推荐

as操作符如何将enum转换为int?

什么样的 struct 可以避免使用RefCell?

如何从接收&;self的方法克隆RC

如何在原始字符串中转义";#和#";

你是如何在铁 rust 一侧的金牛座获得应用程序版本的?

在本例中,为什么我不能一次多次borrow 可变变量?

在生存期内将非静态可变引用转换为范围内的静态可变引用

Rust ndarray:如何从索引中 Select 数组的行

如何迭代存储在 struct 中的字符串向量而不移动它们?

write_buffer 不写入缓冲区而是输出零 WGPU

tokio::spawn 有和没有异步块

Rust 如何返回大类型(优化前)?

trait 对象指针的生命周期

分配给下划线模式时会发生什么?

如何使用泛型满足 tokio 异步任务中的生命周期界限

返回迭代器的特征

如何在 Rust Polars 中可靠地连接 LazyFrames

无法把握借来的价值不够长寿,请解释

如何用另一个变量向量置换 rust simd 向量?

Rust 为什么 (u32, u32) 的枚举变体的大小小于 (u64)?