Rc解引用*s为何不返回引用?borrow与reference有何区别?
关于Rc解引用与借用的核心问题解答
这两个问题都触及了Rust中Deref trait和借用系统的关键逻辑,我来帮你逐一拆解:
1. 为何Rc值的*s不返回引用?
首先得明确Deref trait的实际工作流程:Rc<T>实现了Deref<Target = T>,它的deref方法确实会返回&T——也就是调用s.deref()能拿到指向内部String的&String引用。
但当你使用*操作符时,Rust会自动做一层展开:*s等价于*(s.deref())。这里对deref()返回的&String又执行了一次解引用,所以最终得到的是**String类型的值**,而非引用。
你之所以会预期返回引用,大概率是混淆了deref方法的返回值和*操作符的最终结果。如果想要获取&String,有几种更直接的写法:
- 利用Deref强制转换:
let o: &String = &s;(Rust会自动把&Rc<String>转为&String) - 显式调用
deref:let o: &String = s.deref(); - 先解引用再取引用:
let o: &String = &*s;
而你最初的代码let o: &String = *s;报错,正是因为*s产生的是String类型,无法直接赋值给&String类型的变量。
2. Borrow(借用)和Reference(引用)是同一概念吗?
当然不是!二者是相关但完全不同的概念:
- **Reference(引用)**是Rust中的一种类型,比如
&T或&mut T,它代表对某个值的间接访问权限。 - **Borrow(借用)**是一个动作,指的是创建引用的过程——当你获取一个值的引用时,你就是在“借用”这个值。
回到你遇到的cannot move out of borrowed content错误:当你写let o: String = *s;时,*s展开为*(s.deref()),而s.deref()返回的&String是一个通过借用得到的引用。Rust禁止从引用后移动值,因为移动会让原数据失效,而Rc是共享所有权类型,内部数据可能被多个实例共享,这种移动会破坏内存安全。
总结一下:借用是“获取引用”的行为,引用是这个行为产生的结果类型,二者不能混为一谈。
内容的提问来源于stack exchange,提问作者theicfire
相关产品推荐
相关产品推荐

