【问题标题】:Switching from Box<T> to Rc<T> for a Scheme-like Cons list doesn't compile从 Box<T> 切换到 Rc<T> 以获取类似于 Scheme 的 Cons 列表不会编译
【发布时间】:2018-09-24 19:33:27
【问题描述】:

如果将Rc 替换为Box,则下面的程序将编译并运行。为什么使用引用计数时不编译?这是一个关于Rc&lt;T&gt;Box&lt;T&gt;区别的问题。

use std::rc::Rc;

#[derive(Debug, Clone)]
pub enum ILst {
    Nil,
    Cons(i32, Rc<ILst>),
}

impl ILst {
    pub fn new() -> Self {
        ILst::Nil
    }

    pub fn cons(self, item: i32) -> Self {
        ILst::Cons(item, Rc::new(self)) 
    }

    pub fn car(&self) -> Option<i32> {
        match *self {
            ILst::Cons(u, ref _v) => Some(u),
            ILst::Nil => None,
        }
    }

    pub fn cdr(&self) -> Self {
        match *self {
            ILst::Cons(_u, ref v) => *v.clone(),
            ILst::Nil => ILst::Nil,
        }
    }
}

fn main() {
    let list = ILst::new().cons(17).cons(29);
    let rest = list.cdr();
    println!("list  = {:?}", rest);
}
error[E0507]: cannot move out of borrowed content
  --> src/main.rs:27:38
   |
27 |             ILst::Cons(_u, ref v) => *v.clone(),
   |                                      ^^^^^^^^^^ cannot move out of borrowed content

【问题讨论】:

  • 我相信How do I get an owned value out of a Box?的答案已经回答了你的问题:“因为Box很特别”。如果您不同意,请edit您的问题解释差异。否则,我们可以将此问题标记为已回答。
  • Rc&lt;T&gt;Box&lt;T&gt; 之间的区别——是的,Box is special

标签: rust match refcounting


【解决方案1】:

解决办法好像是替换

*v.clone()

Rc::deref(v).clone()

然后添加一行

use::ops::Deref;

到程序的开头。

【讨论】:

  • 为什么*v 不起作用?前缀* 不是std::ops::Deref 的语法吗? * 是不是其他类型的 deref 操作?
  • 关于上面的评论,是的,这对我来说很有意义。但由于某种原因,事实并非如此。我也想要一个解释。
  • Deref 在以* 调用时表现不同(移出 deref) - 请参阅Why is the return type of Deref::deref itself a reference?。作为替代方案,您通常可以使用&amp;* 取消引用和重新借用,因此该行也可以替换为(&amp;**v).clone()(使用额外的* 撤消ref v)。 (有时 rustc 会建议 &amp;*,但在这种情况下它可能无法识别双重 deref。)
  • 是的,我验证了上面的作品。谢谢你的解释。
猜你喜欢
  • 2021-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-13
  • 1970-01-01
相关资源
最近更新 更多