我被告知的是,一旦一个对象(在此转换中
sth
)实现了 Drop
特征,那么它就可以使用 *
运算符来调用其 deref()
方法。所以我认为使用*
的结果应该与显式调用deref()
的结果相同。但我发现在某些情况下这两个结果并不相等。例如:
use std::ops::Deref;
fn main() {
let sth = Box::new(5);
println!("{:p}", sth.deref());
println!{"{:?}", *sth};
}
我搜索了文档,知道
deref()
的Box
的签名是(&self)->&T
。这意味着它应该返回内部值的引用。然而,*sth
看起来像是直接返回内部值。为什么两个结果不相等?
*
与 v.deref()
不同(或更准确地说是 Deref::deref(&v)
) - 它更像 *Deref::deref(&v)
(注意 *
)。
具体针对
Box
,它可以移出它,例如:
let s = Box::new(String::new());
let moved_out = *s;
// s; // Error, moved out of the `Box`.
无论哪种类型,它都会创建一个位置 - 它可以是
*Deref::deref(&v)
或 *DerefMut::deref_mut(&v)
,具体取决于是否需要可变访问。
正如 Chayim 回答的那样,
deref()
用于获取对内部项目的引用,*
然后实际访问该内部项目。
然而,当谈到
Box
时,你不会发现它的行为受到任何特征的调节(至少到目前为止):Box
是一个语言项目。
虽然与引用不同,它看起来像普通类型,但它确实具有相同的地位,并且位于语言本身的核心。因此,它可以(并且确实)以其他类型无法做到的方式运行。
其中一个行为是取消引用的能力,这是它完全独特的(过去已经为此提出了 RFC,但据我所知,进展甚微)。
尽管在您的具体情况下甚至不涉及:
println!
将始终引用其参数,所以
println!{"{:?}", *sth};
确实如此
let args = Args::new(&*sth);
然后你就得到了值,因为有一个毯子
impl Display for &T where T: Display
委托给 T
的实现(顺便说一句,Box
也是如此)。
您可以通过复制该行来检查它是否工作正常,如果该值已移动(并且该框已删除),则不会出现这种情况。