自动解除引用和解除引用强制之间有啥关系?

Posted

技术标签:

【中文标题】自动解除引用和解除引用强制之间有啥关系?【英文标题】:What is the relation between auto-dereferencing and deref coercion?自动解除引用和解除引用强制之间有什么关系? 【发布时间】:2019-04-19 21:01:25 【问题描述】:

在discussion 之后,我现在对auto-dereferencingderef coercion 之间的关系有点困惑。

It seems 仅当要取消引用的目标是方法接收器时,术语“自动取消引用”才适用, 而it seems 术语“deref coercion”适用于函数参数及其需要的所有上下文。

我认为取消引用并不总是涉及强制取消引用,但我不确定:取消引用是否总是使用一些 Deref::deref 特征实现?

如果是这样,T: Deref<Target = U> where T: &U 的实现者是否内置在编译器中?

最后,在编译器将&&&&x 隐式转换为&x 的所有情况下,使用术语“autoderef”听起来很自然:

pub fn foo(_v: &str) -> bool 
    false


let x="hello world";
foo(&&&&x);

这是社区的普遍共识吗?

【问题讨论】:

【参考方案1】:

这两种情况之间的相似之处是相当肤浅的。

在方法调用表达式中,编译器首先需要确定调用哪个方法。该决定基于接收器的类型。编译器构建一个候选接收器类型列表,其中包括通过重复取消引用接收器获得的所有类型,还包括&T&mut T 遇到的所有类型T。这就是为什么您可以将接收&mut self 的方法直接调用为x.foo() 而不必编写(&mut x).foo() 的原因。对于候选列表中的每种类型,编译器然后查找固有方法和可见特征上的方法。有关详细信息,请参阅language reference。

deref 强制是相当不同的。它只发生在编译器确切知道期望什么类型的强制站点。如果遇到的实际类型与预期类型不同,编译器可以使用任何强制(包括 deref 强制)将实际类型转换为预期类型。可能的强制列表包括未调整大小的强制、指针弱化和 deref 强制。详情请参阅chapter on coercions in the Nomicon。

所以这实际上是两种完全不同的机制——一种用于寻找正确的方法,另一种用于在已知确切期望的类型时转换类型。第一种机制还自动引用接收者,这在强制中永远不会发生。

我认为取消引用并不总是涉及强制取消引用,但我不确定:取消引用是否总是使用一些 Deref::deref 特征实现?

并非每次解除引用都是解除引用强制。如果你写*x,你明确取消引用x。相反,deref coercion 由编译器隐式执行,并且仅在编译器知道预期类型的​​地方执行。

semantics of dereferencing 取决于x 的类型是指针类型,即引用还是原始指针。对于指针类型,*x 表示 x 指向的对象,而对于其他类型,*x 等效于 *Deref::deref(&x)(或 this 的可变类似物)。

如果是,T: Deref<Target = U> where T: &U 的实现者是否内置在编译器中?

我不太确定你的语法应该是什么意思——它肯定不是有效的 Rust 语法——但我猜你问的是编译器中是否内置了将 &T 的实例取消引用到 T 的问题。如上所述,指针类型的解引用,包括引用,是编译器内置的,但标准库中也有一个blanket implementation of Deref for &T。这种一揽子实现对于通用代码很有用 - 特征绑定 T: Deref<Target = U> 否则将不允许 T = &U

【讨论】:

我认为重点在最后一句话。改写我的问题:编译器已知的解引用语义可以称为自动解引用?在强制站点,还有更多 deref coercion 机制,因为正如您所指出的,延迟毯 impl fn deref(&self) -> &T *self 是幂等的,它不能解释 &&&&x -> &x。 @attdona 我跟不上。自动取消引用意味着隐式而不是显式取消引用。它与取消引用的语义无关。在这种情况下,我也无法理解“幂等”这个词。只有当范围是域的子集时,函数才能是幂等的,但这里不是这种情况 - 函数将 &&T 类型的值映射到 &T 类型的值。 我不恰当地使用术语幂等来表示 deref 覆盖实现将 &T 转换为 &T。显然,如果我们将deref() 应用于&&T&&&T,我们得到了&T,但在这种情况下,我看到的主要参与者是自动解除引用。在&&&x.deref() 接收器的自动取消引用之后,deref()&T 返回一个&T:一种无操作操作(我假设deref 它被调用是因为文档声明deref总是被调用,但对我来说,在这种情况下它似乎没用)。哪个术语最能描述正在发生的事情:auto-deref 或 deref coercion? @attdona 对不起,我还是听不懂。一揽子 deref 实现的原型本质上是deref(&&T) -> &T,而您似乎认为它是deref(&T) -> &T。不过,我可能误读了您的评论。 非常感谢您的耐心等待!我错误地认为毯子 impl 为 deref(&T) -> &T,这让我写了无意义的 cmets。

以上是关于自动解除引用和解除引用强制之间有啥关系?的主要内容,如果未能解决你的问题,请参考以下文章

NSTimer解除循环引用

win7显示引用的帐户当前已锁定,且可能无法登录,怎么解除锁定?

使用解除引用的c ++二叉搜索树

解除引用指针C时的类型不完整

变量作用域和内存问题--笔记7

Excel高手请进!谢谢!!如何解除两表之间的公式关联?