内部可変性のある型は、可変と指定されていなくても、特例として値を変更できる。
これは例えば、不変参照により共有される値の更新などで必要となる。
ただし、内部可変性を乱用するとコードが読みにくくなるので注意が必要。
標準で提供される内部可変性のある型について。
UnsafeCell
UnsafeCell
は仕様上の特別な型で、ここで紹介しているその他の型の実装の基盤にもなっている。コンパイラはこの型でラップされた値については、たとえ不変とマークされていても、変更されうるものとして扱う。
UnsafeCell
以外
UnsafeCell
をそのまま使うのは、あまりお勧めできない。なぜなら、内部可変性は普段なら Rust が保証してくれる読込と書込の排他性、それから書込と書込の排他性を失わせる。そのため、バグを書きやすくなる。一方、UnsafeCell
を利用して実装された他の標準の型では、そうした問題をうまく回避できる理論的背景がある場合が多い。そのため、可能な限りそちらを採用した方がよい。
UnsafeCell
Cell
OnceCell
LazyCell
RefCell
OnceLock
OnceCell
の非同期版)。
LazyLock
LazyCell
の非同期版)。
Mutex
RwLock
の簡易版)。
RwLock
RefCell
の非同期版)。
AtomicXXX
AtomicI32
や AtomicU32
など)。
以下では、変数 cell
に mut
の指定はないが、値を変更できる。
use std::cell::Cell;
fn main() {
let cell = Cell::new(42);
cell.set(43);
assert_eq!(cell.get(), 43);
}