スマートポインタ
ポインタは、メモリのアドレスを含む変数の一般的な概念です。このアドレスは、何らかの他のデータを参照、または「指します」。
Rustにおいて、最もありふれた種類のポインタは、参照であり、第4章で習いましたね。参照は、
&
記号で示唆され、指している値を借用します。データを参照すること以外に特別な能力は何もありません。
また、オーバーヘッドもなく、最も頻繁に使われる種類のポインタです。
一方、スマートポインタは、ポインタのように振る舞うだけでなく、追加のメタデータと能力があるデータ構造です。 スマートポインタという概念は、Rustに特有のものではありません: スマートポインタは、C++に端を発し、 他の言語にも存在しています。Rustでは、標準ライブラリに定義された色々なスマートポインタが、 参照以上の機能を提供します。この章で探究する一つの例が、参照カウント方式のスマートポインタ型です。 このポインタにより、所有者の数を追いかけることでデータに複数の所有者を持たせることができ、 所有者がいなくなったら、データの片付けをしてくれます。
所有権と借用の概念を使うRustで、参照とスマートポインタの別の差異は、参照はデータを借用するだけのポインタであることです; 対照的に多くの場合、スマートポインタは指しているデータを所有します。
その時は、スマートポインタとは呼ばなかったものの、第8章のString
やVec<T>
のように、
この本の中でいくつかのスマートポインタに遭遇してきました。これらの型はどちらも、
あるメモリを所有し、それを弄ることができるので、スマートポインタに数えられます。また、
メタデータ(キャパシティなど)や追加の能力、あるいは保証(String
ならデータが常に有効なUTF-8であると保証することなど)もあります。
スマートポインタは普通、構造体を使用して実装されています。スマートポインタを通常の構造体と区別する特徴は、
スマートポインタは、Deref
とDrop
トレイトを実装していることです。Deref
トレイトにより、スマートポインタ構造体のインスタンスは、
参照のように振る舞うことができるので、参照あるいはスマートポインタのどちらとも動作するコードを書くことができます。
Drop
トレイトにより、スマートポインタのインスタンスがスコープを外れた時に走るコードをカスタマイズすることができます。
この章では、どちらのトレイトについても議論し、これらのトレイトがスマートポインタにとって重要な理由を説明します。
スマートポインタパターンがRustにおいてよく使われる一般的なデザインパターンだとして、この章では、全ての既存のスマートポインタを講義しません。 多くのライブラリに独自のスマートポインタがあり、自分だけのスマートポインタを書くことさえできます。 標準ライブラリの最もありふれたスマートポインタを講義します:
- ヒープに値を確保する
Box<T>
- 複数の所有権を可能にする参照カウント型の
Rc<T>
RefCell<T>
を通してアクセスされ、コンパイル時ではなく実行時に借用規則を強制する型のRef<T>
とRefMut<T>
さらに、不変な型が、内部の値を可変化するAPIを晒す内部可変性パターンについても講義します。 また、循環参照についても議論します: 循環参照により、メモリがリークする方法とそれを回避する方法です。
さあ、飛び込みましょう!