Rust 智能指针

在C++11中,会有三种智能指针:
  • unique_ptr。独占内存,不共享。在Rust中是:std::boxed::Box
  • shared_ptr。以引用计数的方式共享内存。在Rust中是:std::rc::Rc
  • weak_ptr。不以引用计数的方式共享内存。在Rust中是:std::rc::Weak

标准库中,有许多我们常见的类型,实现了这个 Deref 操作符。比如 Vec、String、Box、Rc、Arc等。它们都支持"解引用"这个操作。从某种意义上来说,它们都可以算做特种形式的"指针",(像胖指针一样,是带有额外元数据的指针)

&[T],&str 对指向的数组/字符串切片没有所有权,不负责内存空间的分配和释放

自动解引用:&&&&&&&&&&str 类型来调用成员方法,也是可以的。原因就是,Rust编译器帮我们做了隐式的 deref 调用,当它找不到这个成员方法的时候,它会自动尝试使用 deref 方法后再找该方法,一直循环下去。编译器在&&&str类型里面找不到len方法,就尝试将它 deref,变成 &&str 类型,再寻找 len 方法,还是没找到,那么继续deref,变成 &str,现在找到 len 方法了,于是就调用这个方法

在弱引用需要使用内存的时候需要"升级"成强引用 ,但是这个升级可能会不成功,因为内存可能已经被别人清空了。所以,这个操作会返回一个 Option 的枚举值,Option::Some(T) 表示成功了,而 Option::None 则表示失改了。你会说,这么麻烦,我们为什么还要 Weak ? 这是因为强引用的 Rc 会有循环引用的问题……

智能指针smart pointers)是一类数据结构,他们的表现类似指针,但是也拥有额外的元数据和功能

引用计数reference counting, Rc)智能指针类型,其允许数据有多个所有者。引用计数智能指针记录总共有多少个所有者,并当没有任何所有者时负责清理数据
Rc 只能用于单线程场景;Rc 允许通过不可变引用来只读的在程序的多个部分共享数据

修改 Rc 里的值,Rust 会给你两个方法,一个是 get_mut(),一个是 make_mut() ,这两个方法都有副作用或是限制。get_mut() 需要做一个"唯一引用"的检查,也就是没有任何的共享才能修改。make_mut() 则是会把当前的引用给clone出来,再也不共享了, 是一份全新的。

// std::sync::Mutex<()> 互斥锁,一次只有一个线程能访问它的内容(空元组`()`),调用 lock 方法时,如果互斥锁目前正在被别人访问,将阻塞直到它可用为止
// std::sync::Arc; "Arc"代表"原子引用计数",可以在多个线程间共享,线程结束它会变小,Arc的clone()方法用来增加引用计数
// RwLock 允许多个同时读取

在 Rust 中,普通引用和智能指针的一个额外的区别是引用是一类只借用数据的指针;相反大部分情况,智能指针 拥有 他们指向的数据。

Box 只提供了间接存储和堆分配(不需要知道数据大小);他们并没有任何其他特殊的功能,比如我们将会见到的其他智能指针。

实现 Deref trait 允许我们重载 解引用运算符dereference operator)*。// 自动解引用

解引用强制多态deref coercions)是 Rust 出于方便的考虑作用于函数或方法的参数的。其将实现了 Deref 的类型的引用转换为 Deref 所能够将原始类型转换的类型的引用。

Rust 当值离开作用域时自动插入 drop 调用,不能直接禁用这个功能。

析构函数destructor),是一个清理实例的函数的通用编程概念。析构函数 对应创建实例的 构造函数。Rust 中的 drop 函数就是这么一个析构函数。

需要提早清理值,可以使用 std::mem::drop 函数

内部可变性Interior mutability)是 Rust 中的一个设计模式,它允许你即使在有不可变引用时改变数据,这通常是借用规则所不允许的。该模式在数据结构中使用 unsafe 代码来模糊 Rust 通常的可变性和借用规则。RefCell 遵循内部可变性模式。RefCell 并没有完全绕开借用规则,编译器中的借用检查器允许内部可变性并相应的在运行时检查借用规则。如果违反了这些规则,会得到 panic! 而不是编译错误。 // 有时候外部定义不可变,但内部需要修改

// Cell 和 RefCell 提供了 set()/get() 以及 borrow()/borrow_mut() 的方法

测试替身test double)是一个通用编程概念,它代表一个在测试中替代某个类型的类型