Rust 是否可以绘制Rc<;T>;要获得Rc<;子部分-of-T>;?

Rust 是否可以绘制Rc<;T>;要获得Rc<;子部分-of-T>;?,rust,reference-counting,Rust,Reference Counting,我有一个Rc,但需要从中获取Rc。比如: let rc_option: Rc<Option<T>> = Rc::new(Ok(value)); let ok_value: Rc<T> = rc_option.map(|option| option.unwrap()); let rc_选项:rc=rc::new(Ok(value)); 让ok_值为:Rc=Rc_option.map(| option | option.unwrap()); 这有可能吗?这似乎

我有一个
Rc
,但需要从中获取
Rc
。比如:

let rc_option: Rc<Option<T>> = Rc::new(Ok(value));
let ok_value: Rc<T> = rc_option.map(|option| option.unwrap());
let rc_选项:rc=rc::new(Ok(value));
让ok_值为:Rc=Rc_option.map(| option | option.unwrap());

这有可能吗?这似乎是有道理的,因为
Rc
可以增加它内部的计数器,以获得新的映射值,但我找不到任何文档 不,不可能从
Rc
创建一个仍然存在的
Rc
。但是,可以从
Rc
创建
Rc
,同时仍保留后一个变量

长话短说 如果您试图创建一个新的
Rc
,它拥有
Rc
中的
T
,则必须使用原始的
Rc
。您也不能有多个
Rc
,因为这样在指针仍然存在的情况下移动共享值,这是非常不安全的

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

下面是一个例子:

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
    }
}
让rc_选项:rc=rc::new(一些(值));
匹配Rc::try_展开(Rc_选项){
确定(选项)=>{
匹配选项{
一些(t)=>{
让ok_值:Rc=Rc::new(t);
//做一些有价值的事情
}
无=>{
//在这里做点别的
}
}
}
错误(rc_选项)=>{
//有多个所有者,请在此处执行其他操作
}
}
如果您想保留原作,可以这样做:

match &*rc_option {
    Some(ref t) => {
        let ok_ref: Rc<&T> = Rc::new(t);
    }
    None => { /* Do something else, there's no internal value */ }
}
match&*rc\u选项{
一些(参考t)=>{
让ok_ref:Rc=Rc::new(t);
}
None=>{/*执行其他操作,没有内部值*/}
}


编辑:正如Chronial提到的,请注意,
ok\u ref
不能超过
rc\u选项
(因为它是对
rc\u选项
)的引用,这可能不是您希望发生的事情。

正如中的开发者所述,这是标准库不支持的。您可以自己实现这样的功能:

use std::ops::Deref;

#[derive(Clone)]
struct RcSome<T>(Rc<Option<T>>);

impl<T> RcSome<T> {
    fn from(rc: &Rc<Option<T>>) -> RcSome<T> {
        RcSome(rc.clone())
    }
}

impl<T> Deref for RcSome<T> {
    type Target = T;
    fn deref(&self) ->  &T {
        self.0.as_ref().as_ref().unwrap()
    }
}
使用std::ops::Deref;
#[衍生(克隆)]
结构体(Rc);
简单的{
fn from(rc:&rc)->RcSome{
RcSome(rc.clone())
}
}
为RcSome执行命令{
类型目标=T;
fn-deref(&self)->&T{
self.0.as_ref().as_ref().unwrap()
}
}
那你就可以这么做了

let rc_option: Rc<Option<T>> = Rc::new(Some(value));
let ok_value: RcSome<T> = RcSome::from(&rc_option);
让rc_选项:rc=rc::new(一些(值));
让ok_值:RcSome=RcSome::from(&rc_选项);
请注意,如果
rc\u选项
包含
None
,则会死机。但是
ok\u值
现在的行为将类似于
Rc
——也就是说,您可以
克隆()
它并执行
ok\u值<代码>ok_值
也不会与
rc_选项
共享生命周期,因此它可以比rc的寿命更长。

不与rc共享生命周期。 这在
Rc
中是不可能的,因为它的内存布局:

//  Equivalence:
struct RcBox<T> {
    strong: AtomicUsize,
    weak: AtomicUsize,
    data: T,
};

struct Rc<T> {
    ptr: *const RcBox<T>,
};
从理论上讲,这一个可以允许映射。。。然而,在上面创建一个安全的接口可能并不容易

如何防止用户在
map
中返回不相关的生存期?保证返回引用的生存期超过flex的生存期是否足够安全

fn fool(flex: FlexRc<Option<i32>>) -> FlexRc<i32> {
    let i = 3;
    flex.map(|_| &i)
}
fn傻瓜(flex:FlexRc)->FlexRc{
设i=3;
flex.map(| | |&i)
}

如果内部
选项为
None
,您会得到什么?“这似乎是有意义的事情”,一点也没有。另外,如果您结束使用
选项
是有原因的,那么为什么要删除
选项
?如果你不需要它,就不要使用<代码>选项>代码> Re:Op选项,它只是试图在一个结构中始终存在一个字段。@ StAdvuru:可以用C++ <代码> SydDypTrp>代码来获得一个字段,或者一个数组的元素,并共享相同的“计数器”。@ MatthieuM。我看不出理性,这似乎非常不安全,如果最后一个
共享的
不包含好的
ptr
,基本上如何释放
ptr
?这似乎打破了共享的api。可能应该注意的是,新的Rc将有它的生命周期绑定到原始Rc(即,它不能超过它),这可能不是你想要的。你是对的。我将更新我的答案以提及这一点。谢谢,这有助于我的理解。
&T
副本
,因此在新的
Rc
中填充它是没有意义的,因为它不能延长原始
T
的寿命。您也可以在
匹配中使用
t
,我只将
&t
放在
Rc
中(在本例中),因为他们希望将值映射到
Rc
。我展示了如何生成一个包含原始值的
Rc
,而不使用它,但也受到原始值生存期的限制。嗯,是的,如果你可以强制在Rc中返回值的一个子部分,这会安全吗?比如,若它是一个结构,那个么确保它只是一个有值的字段?不知道你会怎么做。@CallumRogers:那会很安全的。。。虽然我刚刚意识到它会泄漏:)计数器需要知道原始指针,并有一个函数来运行其析构函数。不过,我不知道如何正确地强制执行生存期关系。@CallumRogers:所以,在
计数器中添加了析构函数,因为它是数据的实际所有者。对于生存期关系,我认为我们可以约束lambda接受的生存期:
FnOnce
fn fool(flex: FlexRc<Option<i32>>) -> FlexRc<i32> {
    let i = 3;
    flex.map(|_| &i)
}