Why is the return type of Deref::deref itself a reference?
我正在阅读Rust的Deref特性的文档:
1 2 3 4
| pub trait Deref {
type Target: ?Sized;
fn deref(&self) -> &Self::Target;
} |
Deref函数的类型签名对我来说似乎违反直觉。 为什么返回类型是引用? 如果引用实现了此特性,因此可以将其取消引用,这将产生什么影响?
我能提出的唯一解释是,引用未实现Deref,但被认为是"原始可解除引用"。 但是,如何编写适用于任何可解除引用的类型(包括Deref< T >和&T)的多态函数呢?
-
这可能会让您感兴趣reddit.com/r/rust/comments/2umad5/
-
@JonasTepe因此,如果我正确理解了这一点,原因是我们无法指定返回左值的函数,因此我们通过返回对已有的左值的引用来"手动"执行此操作?
-
您可能要返回"正确的" l值。表示自身拥有的值(Deref的值实现者)。您不想返回一些短暂的左值。然后,您也可以返回一个右值。这样做的唯一方法是将引用返回给self。
-
@JonasTepe您如何无法返回正确的左值?
-
我只想说明为什么Deref需要返回引用。至于引用本身,您可以引用一个引用。那么,为什么不希望取消引用它们呢?他们实际上都实现了Deref。
-
@JonasTepe但是,如果目标是取消引用的引用,那有什么意义呢?您是否仅会收到另一个指向原始对象指向的对象的引用?
-
Deref特质启用" * ptr"操作。如果无法为所有引用实现该功能,则无法取消引用它们。 Deref特征存在,因此可以使用此语法使用更多类型(除引用之外)(例如,智能指针如Rc或Arc)。它是取消引用操作的概括。
-
@JonasTepe假设您有一个引用x指向某个对象y。您编写*x,并调用deref。它所做的只是返回对y的另一个引用,因为这就是其含义(和实现)。您现在可以访问该对象吗?否。因为它仍然是参考。您回到了起点。这不能作为参考的实现方式吗?
-
对于普通参考,这正是它的作用。他们只是在实现中返回自己。但是,调用deref方法的方式有所不同。 std :: ops中的每个特征都是一个运算符,编译器专门处理这些特征。围栏:play.rust-lang.org/
-
@jco *x不是所谓的deref。 *x取消引用& -ptr。 deref允许不是引用的对象假装为引用。 Box< T >的作用类似于&T。参见github.com/rust-lang/rfcs/blob/master/text/。
-
这是交叉发布到Reddit
-
如果将特征称为AsRef,则可能会减少混乱。不幸的是,我们已经有了一个具有该名称的特征...
that references don't implement Deref
您可以看到实现Deref的所有类型,并且&T在该列表中:
1
| impl<'a, T> Deref for &'a T where T: ?Sized |
不明显的是,当您将*运算符与实现Deref的东西一起使用时,会应用语法糖。看看这个小例子:
1 2 3 4 5 6 7
| use std::ops::Deref;
fn main() {
let s: String ="hello".into();
let _: () = Deref::deref(&s);
let _: () = *s;
} |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| error[E0308]: mismatched types
--> src/main.rs:5:17
|
5 | let _: () = Deref::deref(&s);
| ^^^^^^^^^^^^^^^^ expected (), found &str
|
= note: expected type `()`
found type `&str`
error[E0308]: mismatched types
--> src/main.rs:6:17
|
6 | let _: () = *s;
| ^^ expected (), found str
|
= note: expected type `()`
found type `str` |
对Deref的显式调用返回&str,但是运算符*返回str。更像是您在调用*Deref::deref(&s),而忽略了隐式无限递归。
Xirdus的说法正确
If deref returned a value, it would either be useless because it would always move out, or have semantics that drastically differ from every other function
尽管"无用"有点强;它对于实现Copy的类型仍然有用。
也可以看看:
-
为什么对Deref :: deref的结果进行断言会因类型不匹配而失败?
请注意,以上所有内容对于Index和IndexMut同样有效。
编译器仅知道如何取消引用&指针-但它也知道实现Deref特征的类型具有deref()方法,该方法可用于获取对给定对象内部内容的适当引用。如果取消引用对象,则实际要做的是先获取引用,然后再取消引用。
如果deref()返回一个值,则它要么会因为总是移出而变得无用,要么具有与其他所有函数完全不同的语义,这不是很好。