Deref<T>

17 Mar 2025 | 4 分钟阅读
  • Deref<T> trait 用于自定义解引用运算符 (*) 的行为。
  • 如果实现 Deref<T> trait,则可以将智能指针视为引用。 因此,也可以在智能指针上使用适用于引用的代码。

常规引用

常规引用是一种指向存储在其他地方的某个值的指针。 让我们看一个简单的示例,创建一个 i32 类型值的引用,然后我们将解引用运算符与此引用一起使用。

输出

a and *b are equal

在上面的示例中,a 包含 i32 类型值 20,而 b 包含变量 'a' 的引用。 如果我们使用 *b,则它表示值 20。 因此,我们可以比较变量 a 和 *b,它将返回 true 值。 如果我们使用 &b 而不是 *b,则编译器会抛出一个错误 “无法将 {integer} 与 {&integer} 进行比较”

Box<T> 作为引用

Box<T> 指针可以用作引用。

让我们看一个简单的例子

输出

Value of *b is 11

在上面的示例中,Box<T> 的行为与常规引用类似。 它们之间的唯一区别是 b 包含指向数据的 box,而不是使用 '&' 运算符引用该值。

智能指针作为引用

现在,我们创建类似于 Box<T> 类型的智能指针,我们将看到它们与常规引用的行为有何不同。

  • Box<T> 可以定义为具有一个元素的元组结构,例如 MyBox<T>。
  • 创建元组结构后,我们在 MyBox<T> 类型上定义函数。

让我们看一个简单的例子

输出

Rust Deref

在上面的示例中,我们创建了智能指针 b,但它无法被解引用。 因此,我们得出结论,类似于 Box<T> 类型的自定义指针无法被解引用。

实现 Deref Trait

  • Deref trait 在标准库中定义,用于实现名为 deref 的方法。
  • deref 方法借用 self 并返回对内部数据的引用。

让我们看一个简单的例子

输出

10

程序说明

  • Deref trait 在 MyBox 类型上实现。
  • Deref trait 实现了 deref() 方法,并且 deref() 方法返回变量 'a' 的引用。
  • 类型 Target = T; 是 Deref trait 的关联类型。 关联类型用于声明泛型类型参数。
  • 我们创建 MyBox 类型 b 的实例。
  • deref() 方法通过使用 MyBox 类型 b.deref() 的实例来调用,然后解引用从 deref() 方法返回的引用。

Deref 强制转换

  • Deref 强制转换是将实现 Deref trait 的引用转换为 Deref 可以将原始类型转换成的引用的过程。
  • Deref 强制转换在函数和方法的参数上执行。
  • 当我们传递特定类型的引用给一个函数,该函数的类型与函数定义中的参数类型不匹配时,Deref 强制转换会自动发生。

让我们看一个简单的例子

输出

5

在上面的示例中,我们使用参数 &b 调用 print(&b) 函数,该参数是 &Box<i32> 的引用。 在这种情况下,我们实现 Deref trait,它通过 Deref 强制转换过程将 &Box<i32> 转换为 &i32。

Derif 强制转换与可变性的交互

到目前为止,我们使用 Deref Trait 来覆盖不可变引用上的 * 运算符,并且可以使用 DerefMut trait 来覆盖可变引用上的 * 运算符。

Rust 在以下三种情况下执行 Deref 强制转换

  • 当 T: Deref<Target = U> 且 T 和 U 是不可变引用时,&T 将转换为 &U 类型。
  • 当 T: DerefMut<Target = U> 且 T 和 U 是可变引用时,&mut T 将转换为 &mut U。
  • 当 T: Deref<Target = U> 且 T 是可变引用且 U 是不可变引用时,&mut T 将转换为 &U。

注意:由于借用规则,Rust 可以将可变引用强制转换为不可变引用,但它不能将不可变引用强制转换为可变引用。


下一个主题Drop Trait