我在阅读Rust的Deref
trait的文档:
pub trait Deref {
type Target: ?Sized;
fn deref(&self) -> &Self::Target;
}
字符串deref
函数的类型签名对我来说似乎是违反直觉的;为什么返回类型是引用?如果引用实现了这个trait,那么它们可以被解引用,这会有什么影响呢?
我能想到的唯一解释是引用并没有实现Deref
,而是被认为是“可重复解引用的”。然而,如何编写一个多态函数,它将适用于 * 任何 * 可解引用的类型,包括Deref<T>
和&T
?
3条答案
按热度按时间hwamh0ep1#
引用不实现
Deref
你可以看到all the types that implement
Deref
,&T
在这个列表中:字符串
不明显的是,当您将
*
运算符与实现Deref
的东西一起使用时,会应用语法糖。看看这个小例子:的数据
对
deref
的显式调用返回&str
,但运算符*
返回str
。这更像是调用*Deref::deref(&s)
,忽略了隐含的无限递归(参见文档)。Xirdus is correct in saying的
如果
deref
返回一个值,它要么是无用的,因为它总是会被移出,要么具有与其他函数截然不同的语义虽然“无用”有点强,但它仍然对实现
Copy
的类型有用。另请参阅:
请注意,以上所有内容对于
Index
和IndexMut
也有效。unftdfkk2#
编译器只知道如何解引用&-指针--但它也知道实现
Deref
trait的类型有一个deref()
方法,可以用来获取对给定对象内部某些内容的适当引用。如果解引用一个对象,实际上你要做的是首先获取引用,然后才解引用它。如果
deref()
返回一个值,它要么是无用的,因为它总是会被移出,要么具有与其他函数截然不同的语义,这并不好。pes8fvy93#
去引用是两个部分的操作。一个是引用数据,另一个是访问引用后面的数据--这是在去引用操作符
*
的帮助下完成的。Deref
trait只完成第一部分--引用然后给我们。然后去引用操作符*
跟随引用(内存地址),并让我们访问该内存地址上的数据-这部分确实是编译器的内置功能。字符串
现在,如果我们没有引用,我们如何使用解引用操作符
*
访问数据?型
现在
Deref
trait可以为我们自己的类型实现了。型
在
*d
编译器的幕后,从Deref
trait调用deref
方法,如d.deref()
,它给出了一个引用,然后在解引用操作符*
的帮助下,解引用操作让我们访问数据。这里的Deref
trait完成了给我们一个引用的第一部分。