スマートポインタ
ポインタは、メモリ内のアドレスを含む変数を指す一般的な概念です。このアドレスは、ほかの何らかのデータを参照し、つまり「指し示し」ます。Rust で最も一般的な種類のポインタは参照であり、これについては第4章で学びました。参照は & 記号で示され、指している値を借用します。参照には、データを参照する以外の特別な機能はなく、オーバーヘッドもありません。
一方、スマートポインタ は、ポインタのように振る舞いながら、追加のメタデータや機能も持つデータ構造です。スマートポインタという概念は Rust 固有のものではありません。スマートポインタは C++ に由来し、ほかの言語にも存在します。Rust には、参照が提供する機能を超える機能を提供するさまざまなスマートポインタが標準ライブラリに定義されています。一般的な概念を探るために、ここではいくつか異なるスマートポインタの例を見ていきます。その中には、参照カウント を行うスマートポインタ型も含まれます。このポインタは、所有者の数を追跡し、所有者がいなくなったときにデータをクリーンアップすることで、データが複数の所有者を持てるようにします。
Rust では、所有権と借用という概念があるため、参照とスマートポインタの間にはさらに別の違いがあります。参照はデータを借用するだけですが、スマートポインタは多くの場合、自分が指しているデータを_所有_します。
スマートポインタは通常、構造体を使って実装されます。通常の構造体とは異なり、スマートポインタは Deref トレイトと Drop トレイトを実装します。Deref トレイトにより、スマートポインタ構造体のインスタンスは参照のように振る舞えるため、参照にもスマートポインタにも対応するコードを書くことができます。Drop トレイトにより、スマートポインタのインスタンスがスコープを抜けるときに実行されるコードをカスタマイズできます。この章では、これら両方のトレイトについて説明し、それらがスマートポインタにとってなぜ重要なのかを示します。
スマートポインタのパターンは Rust で頻繁に使われる一般的な設計パターンであるため、この章では既存のすべてのスマートポインタを扱うわけではありません。多くのライブラリは独自のスマートポインタを持っており、自分でスマートポインタを書くこともできます。ここでは、標準ライブラリにある最も一般的なスマートポインタを取り上げます。
Box<T>: ヒープに値を確保するためのものRc<T>: 複数の所有権を可能にする参照カウント型Ref<T>とRefMut<T>:RefCell<T>を通じてアクセスされる型で、借用ルールをコンパイル時ではなく実行時に強制するもの
さらに、不変な型が内部の値を変更するための API を公開する 内部可変性 パターンについても扱います。また、参照サイクルについても説明します。参照サイクルがどのようにメモリリークを引き起こすのか、そしてそれをどう防ぐのかを見ていきます。
それでは始めましょう!