是否可以映射Rc <T>以获得Rc <Subpart-of-T>?

Cal*_*ers 3 reference-counting rust

我有一个Rc<Option<T>>但需要得到Rc<T>它.就像是:

let rc_option: Rc<Option<T>> = Rc::new(Ok(value));
let ok_value: Rc<T> = rc_option.map(|option| option.unwrap());
Run Code Online (Sandbox Code Playgroud)

这甚至可以远程实现吗?它看起来像是有意义的东西,因为它Rc可以在内部为新的映射值递增计数器,但我找不到任何文档.

Tha*_*per 7

简答

不,这是不可能创建一个Rc<T>Rc<Option<T>>离开仍然存在后者.Rc<&T>然而,可以从a 创建一个Rc<Option<T>>,同时仍然保留后一个变量.

答案很长

如果您正在尝试创建一个Rc<T>拥有T内部的新内容,Rc<Option<T>>则必须使用原始内容Rc<Option<T>>.你也不能拥有多个实例Rc<Option<T>>,因为当你指针仍然存在时,你正在移动共享值,这是非常不安全的.

但有一种方法可以安全地做到这一点!使用时Rc::try_unwrap,您可以尝试将值移出,但如果Rc存在多个原始实例,则会返回错误.请记住,您还必须处理Option<T>最终出现的情况None.

这是一个例子:

let rc_option: Rc<Option<T>> = Rc::new(Some(value));

match Rc::try_unwrap(rc_option) {
    Ok(option) => {
        match option {
            Some(t) => {
                let ok_value: Rc<T> = Rc::new(t);
                // Do something with ok_value
            }
            None => {
                // Do something else here
            }
        }
    }
    Err(rc_option) => {
        // There are multiple owners, do something else here
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您想保留原件,可以这样做:

match &*rc_option {
    Some(ref t) => {
        let ok_ref: Rc<&T> = Rc::new(t);
    }
    None => { /* Do something else, there's no internal value */ }
}
Run Code Online (Sandbox Code Playgroud)

编辑:正如Chronial所提到的,请注意,ok_ref它不能超过rc_option(因为它是一个参考rc_option),这可能不是你想要发生的.

  • `&T`是'复制',所以在新的`Rc'中填充它真的没有意义,因为它不能延长原始`T`的寿命.你也可以在`match`中使用`t` (2认同)