我似乎无法找出原因:
let a = Box::new(5i32);
let _:() = *a;
告诉我第二行的分配类型是i32
而不是&i32
,因为Deref.deref()
(我假设是在*a
调用的),返回{{ 1}}。
另外,如果我自己打电话给&T
:
deref()
我得到了预期的let _:() = <Box<i32> as Deref>::deref(&a);
。
答案 0 :(得分:7)
取消引用不一定产生(中间)值。考虑
let b = Box::new(1);
(*b).clone();
使用i32::clone()
参数调用方法&self
,其中引用指向框内的值,而不是(*b)
可能产生的临时值。
特征Deref
是实施解除引用的一部分(就像DerefMut
)。
*
可以在盒子上另外做什么没有相应的特性:移出内部值并丢弃该框;这通俗地称为DerefMove
,但在此时仍然是编译器硬编码的盒子专业。
当编译器看到(*a)
时,必须推断是否使用Deref
,DerefMut
或“DerefMove
”;从表达式的使用方式推断:如果您在结果上调用&self
方法,则使用Deref
,例如。
已编辑:固有可复制类型(特征Copy
),使用Deref
后跟副本而不是“DerefMove
”;然后它不再适用于Box,但适用于所有智能指针。
答案 1 :(得分:6)
*foo
与调用foo.deref()
不同。如果是,您永远不会能够实际取消引用某个值。 ^ _ ^
*
是“call Deref::deref
的语法糖,然后进入提供的地址”。这正是人们对该运营商的期望。存在Deref
以使其可扩展。
最后一点掩盖了bluss' answer covers much better。
的一些细节