Rust中智能指针与Deref强制

Rust 中的 Deref 强制转换是一个强大而方便的功能,它允许您更互换地处理智能指针和拥有的值。

它本质上是让编译器自动将对实现 Deref trait的类型的引用转换为对其基础数据的引用。

Deref是 Rust 中的一个特征,定义了如何“取消引用”一个值。这意味着它允许您访问存储在引用或智能指针中的基础数据。

deref 强制如何工作?
当您传递对实现 Deref 的值的引用时,Rust 会自动将其转换为对基础数据类型的引用。这发生在幕后,无需您编写任何显式代码。
deref 强制的好处:

  • 简单性: Deref 强制使代码更加简洁和可读。您不需要一直手动取消引用值。
  • 灵活性:您可以在许多情况下无缝地使用智能指针和自有值。
  • 安全: Deref 强制会进行类型检查,因此可确保您仅访问对基础类型有效的数据。

与 C++ 等语言中主要用于引用内存位置的指针不同,Rust 的智能指针,例如 Box<T>、Rc<T> 和 RefCell<T>、管理其所持有数据的生命周期。这种管理包括自动内存释放和引用计数等功能,在不牺牲效率的情况下确保内存安全。

最简单的智能指针:Box<T>
通过 Box<T>,您可以将底层值存储在堆上,从而有效地移动值,防止深度复制。
移动一个 Box<T> 意味着只有指针被复制,而不是潜在的大的底层值。

让我们看看 Rust 如何让我们像普通指针一样取消引用 Box<T>。

fn main() {
    //值在栈stack中
    let x = 10;
   
// 指向 x 的常规指针
    let x_ptr = &x;
   
// Dereferencing 取消引用
    println!(
"Value using regular pointer: {}", *x_ptr); 

   
// 指向堆上整数的智能指针 (Box)
    let x = Box::new(10);
   
// 自动发生对底层值的取消引用
    println!(
"Value using smart pointer: {}", *x); 
}

尽管 Box<T> 本身是一个轻量级值,包含有关堆存储数据的元数据,但它与普通指针类似,可以使用反引用操作符 (*) 来访问它所持有的值。

这就是 Box<T> 和它的朋友们被称为智能指针的原因。

但是,是什么允许像 Box<T> 这样的类型被取消引用呢?

自定义智能指针
让我们尝试创建自己的类似 Box<T> 的智能指针。为了简单起见,底层值将存储在堆栈而不是堆上。

struct MyType {
    value: i32,
}

impl std::ops::Deref for MyType {
    type Target = i32;

    fn deref(&self) -> &Self::Target {
        &self.value
    }
}

fn main() {
    let my_instance = MyType { value: 42 };
    
    //无 deref 强制
    let explicit_value: &i32 = &(*my_instance);

   
// 使用 deref 强制
    let coerced_value: &i32 = my_instance;

    assert_eq!(explicit_value, coerced_value);
}

在此示例中,MyType 实现了 Deref 特征,允许在以下上下文中使用 MyType 的实例:预计会引用 i32。 Deref 强制在需要时自动应用取消引用操作,使代码更加简洁和可读。

要记住的事情:

  • Deref 强制消除了使用 & 和 * 添加显式引用和取消引用的需要
  • Deref 强制仅适用于引用。您不能直接取消引用拥有的值。
  • 仅当类型使用函数或上下文期望的目标类型实现Deref时,Deref 强制才有效。
  • Deref 强制发生在编译时,因此不会产生任何运行时损失。