我似乎无法弄清楚为什么:
let a = Box::new(5i32);
let _:() = *a;
这告诉我第二行分配的类型是i32
而不是&i32
,因为Deref.deref()
(我假设在*a
处被调用)返回&T
。
此外,如果我自己调用deref()
:
let _:() = <Box<i32> as Deref>::deref(&a);
我得到了预期的&i32。
我似乎无法弄清楚为什么:
let a = Box::new(5i32);
let _:() = *a;
这告诉我第二行分配的类型是i32
而不是&i32
,因为Deref.deref()
(我假设在*a
处被调用)返回&T
。
此外,如果我自己调用deref()
:
let _:() = <Box<i32> as Deref>::deref(&a);
解引用并不一定会产生一个(中间)值。考虑
let b = Box::new(1);
(*b).clone();
使用方法 i32::clone()
时,需要传递一个 &self
参数,这个引用指向盒子内部的值,而不是可以通过 (*b)
产生的临时值。
特性Deref
是实现解引用操作的一部分(就像DerefMut
一样)。
没有对应于box上可以额外执行的 *
的特征:将内部值移出并丢弃盒子;这在俚语中称为 DerefMove
,但仍然是编译器硬编码的 box 特性。
当编译器看到 (*a)
时,它必须推断是否使用 Deref
、DerefMut
或“DerefMove
”;它是从表达式的使用方式推断的,例如,如果在结果上调用一个 &self
方法,则使用 Deref
。
编辑:固有可复制类型(trait Copy
),使用 Deref
,然后进行复制,而不是“DerefMove
”;这将不再限于 Box,而适用于所有智能指针。
*foo
并不等同于调用foo.deref()
。如果是这样的话,你根本无法对值进行解引用。^_^
*
是“调用Deref::deref
然后进入提供的地址”的语法糖。这正是人们从该运算符所期望的。 Deref
的存在是为了使其可扩展。Box
有一个as_ref()
实现,它只是返回内部值的引用:
let a = Box::new(5i32);
let _: &i32 = &a;
Box
,它也适用于引用。当然,你实际上不能搬移出一个引用,但它会尝试。 - ShepmasterDeref.deref()
在Box
上实现时进行了共享借用(即&self
),它保留了Box
的原始所有者。我理解得对吗? - MansourBox<i32>
,(*a).clone()
的情况也不会复制整数,因为您使用指向盒子内部的引用进行调用。 - bluss