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