在 Rust 标准库中有几种包装类型:
std::cell
模块 中的单元格(cell):Cell
和RefCell
- 计数引用包装,如
Rc
和Arc
std::sync
模块 中的类型:例如Mutex
或AtomicBool
据我所知,这些都是提供了比简单引用更多可能性的包装器(wrapper)。虽然我了解一些基础知识,但我看不到整个图片。
它们确切地做什么?单元格(cell)和计数引用家族是否提供相似或正交的功能?
在 Rust 标准库中有几种包装类型:
std::cell
模块 中的单元格(cell):Cell
和 RefCell
Rc
和 Arc
std::sync
模块 中的类型:例如 Mutex
或 AtomicBool
据我所知,这些都是提供了比简单引用更多可能性的包装器(wrapper)。虽然我了解一些基础知识,但我看不到整个图片。
它们确切地做什么?单元格(cell)和计数引用家族是否提供相似或正交的功能?
Box
是 unique_ptr
的替代品,Arc
是 shared_ptr
的替代品,Rc
是 shared_ptr
的非线程安全版本。而 Cell
提供了类似于 mutable
的功能,但是还有额外的保证以避免别名问题。可以将 Cell
看作是 std::atomic
,而 RefCell
则是 std::shared_mutex
的非线程安全版本(如果锁已被占用,则会抛出异常而不是阻塞)。
感谢Matthieu的好回答,这里有一张图可以帮助人们找到他们需要的包装器:
+-----------+
| Ownership |
+--+--------+ +================+
| +-Static----->| T |(1)
| | +================+
| |
| | +================+
| +-----------+ | Local Val| Cell<T> |(1)
+-Unique-->| Borrowing +--+-Dynamic---->|----------------|
| +-----------+ | Ref| RefCell<T> |(1)
| | +================+
| |
| | +================+
| | Threaded | AtomicT |(2)
| +-Dynamic---->|----------------|
| | Mutex<T> |(1)
| | RwLock<T> |(1)
| +================+
|
|
| +================+
| +-No--------->| Rc<T> |
| | +================+
| Locally +-----------+ |
+-Shared-->| Mutable? +--+ +================+
| +-----------+ | Val| Rc<Cell<T>> |
| +-Yes-------->|----------------|
| Ref| Rc<RefCell<T>> |
| +================+
|
|
| +================+
| +-No--------->| Arc<T> |
| | +================+
| Shared +-----------+ |
+-Between->| Mutable? +--+ +================+
Threads +-----------+ | | Arc<AtomicT> |(2)
+-Yes-------->|----------------|
| Arc<Mutex<T>> |
| Arc<RwLock<T>> |
+================+
T
可以被替换为 Box<T>
T
是一个 bool
或数字时,请使用 AtomicT
要知道何时应该使用 Mutex
还是 RwLock
,请参见这个相关问题。