指针就是指向内存的一个地址。最常见的指针就是 Rust 里面的引用。智能指针就是一个结构体,行为类似指针,但是也有额外的元数据和功能。由于 Rust 有所有权机制跟借用,指针跟智能指针会有一个额外的区别,引用通常是借用数据,但是智能指针一般都是拥有数据。

智能指针的优点

  1. 可以自动解引用,提升开发体验
    • 点调用操作自动解引用
    • 函数参数自动解引用
  2. 可以自动化管理内存

使用自动解引用需要注意的地方:

  1. 使用 *x 这样解引用的方式,等价于 *(x.deref())
  2. 使用点操作或在函数参数位置对 x 自动解引用则是等价于 x.deref()

Deref 和 Drop trait

智能指针一般是用结构体来实现,也会去实现 Deref 和 Drop trait。Deref trait 用于重载解引用运算符,Drop trait 用于释放资源。这是他们的定义。

pub trait Deref {
    type Target: ?Sized;

    // Required method
    fn deref(&self) -> &Self::Target;
}

pub trait Drop {
    // Required method
    fn drop(&mut self);
}

下面用 Box 来看看这两个 trait 的是怎么实现的。

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized, A: Allocator> Deref for Box<T, A> {
    type Target = T;

    fn deref(&self) -> &T {
        &**self
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Box<T, A> {
    #[inline]
    fn drop(&mut self) {
        // the T in the Box is dropped by the compiler before the destructor is run

        let ptr = self.0;

        unsafe {
            let layout = Layout::for_value_raw(ptr.as_ptr());
            if layout.size() != 0 {
                self.1.deallocate(From::from(ptr.cast()), layout);
            }
        }
    }
}

常见的智能指针

  • Box:用于在堆上分配内存
  • String 和 Vec
    • 拥有所有权,增加了元数据和额外功能
  • Rc:引用计数智能指针
  • Arc:多线程环境下的引用计数智能指针