【问题标题】:Why is the return type of Deref::deref itself a reference?为什么 Deref::deref 本身的返回类型是引用?
【发布时间】:2015-10-15 23:09:57
【问题描述】:

我正在阅读有关 Rust 的 Deref 特征的文档:

pub trait Deref {
    type Target: ?Sized;
    fn deref(&self) -> &Self::Target;
}

deref 函数的类型签名对我来说似乎违反直觉;为什么返回类型是引用?如果引用实现了这个 trait 以便它们可以被取消引用,这会产生什么影响?

我能想到的唯一解释是引用没有实现Deref,但被认为是“原始可取消引用”。但是,如何编写适用于任何可解引用类型(包括Deref<T> 和&T)的多态函数呢?

【问题讨论】:

  • 这可能会让你感兴趣reddit.com/r/rust/comments/2umad5/…
  • @JonasTepe 所以如果我理解正确,原因是我们不能指定返回左值的函数,所以我们通过返回对我们已经拥有的左值的引用来“手动”执行它?
  • 您希望返回“正确”的左值。表示 self 拥有的值(Deref 的值实现者)。您不想返回一些短暂的左值。然后你也可以返回一个右值。这样做的唯一方法是将引用返回给 self。
  • @jco *x 不是所谓的deref,可以这么说。 *x 取消引用 &-ptr。 Deref 允许不是对 pretend 的引用的对象作为引用,也就是。 Box<T> 可以像 &T 一样工作。见github.com/rust-lang/rfcs/blob/master/text/…。
  • 如果特征被称为AsRef,这可能不会那么混乱。不幸的是,我们已经有了这个名字的特征......

标签: pointers reference rust


【解决方案1】:

引用没有实现Deref

您可以看到all the types that implement Deref,而&T 在该列表中:

impl<'a, T> Deref for &'a T where T: ?Sized

不明显的是,当您将* 运算符与实现Deref 的东西一起使用时,会应用语法糖。看看这个小例子:

use std::ops::Deref;

fn main() {
    let s: String = "hello".into();
    let _: () = Deref::deref(&s);
    let _: () = *s;
}
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 的显式调用返回&amp;str,但运算符* 返回str。这更像是你在调用*Deref::deref(&amp;s),忽略了隐含的无限递归(see docs)。

Xirdus is correct in saying

如果deref 返回一个值,它要么无用,因为它总是会移出,要么具有与其他所有函数截然不同的语义

虽然“没用”有点强;它对于实现 Copy 的类型仍然有用。

另见:

请注意,以上所有内容对于Index 和IndexMut 也是有效的。

【讨论】:

    【解决方案2】:

    编译器只知道如何取消引用 & 指针 - 但它也知道实现 Deref 特征的类型有一个 deref() 方法,可用于获取对给定对象内某些内容的适当引用。如果你取消引用一个对象,你实际上要做的是首先获取引用,然后才取消引用它。

    如果deref() 返回一个值,它要么无用,因为它总是会移出,要么具有与其他所有不好的函数截然不同的语义。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-17
      • 2022-10-14
      • 1970-01-01
      • 2017-12-18
      相关资源
      最近更新 更多