スマートポインタ

ポインタは、メモリのアドレスを含む変数の一般的な概念です。このアドレスは、何らかの他のデータを参照、または「指します」。 Rustにおいて、最もありふれた種類のポインタは、参照であり、第4章で習いましたね。参照は、 &記号で示唆され、指している値を借用します。データを参照すること以外に特別な能力は何もありません。 また、オーバーヘッドもなく、最も頻繁に使われる種類のポインタです。

一方、スマートポインタは、ポインタのように振る舞うだけでなく、追加のメタデータと能力があるデータ構造です。 スマートポインタという概念は、Rustに特有のものではありません: スマートポインタは、C++に端を発し、 他の言語にも存在しています。Rustでは、標準ライブラリに定義された色々なスマートポインタが、 参照以上の機能を提供します。この章で探究する一つの例が、参照カウント方式のスマートポインタ型です。 このポインタにより、所有者の数を追いかけることでデータに複数の所有者を持たせることができ、 所有者がいなくなったら、データの片付けをしてくれます。

所有権と借用の概念を使うRustで、参照とスマートポインタの別の差異は、参照はデータを借用するだけのポインタであることです; 対照的に多くの場合、スマートポインタは指しているデータを所有します。

その時は、スマートポインタとは呼ばなかったものの、第8章のStringVec<T>のように、 この本の中でいくつかのスマートポインタに遭遇してきました。これらの型はどちらも、 あるメモリを所有し、それを弄ることができるので、スマートポインタに数えられます。また、 メタデータ(キャパシティなど)や追加の能力、あるいは保証(Stringならデータが常に有効なUTF-8であると保証することなど)もあります。

スマートポインタは普通、構造体を使用して実装されています。スマートポインタを通常の構造体と区別する特徴は、 スマートポインタは、DerefDropトレイトを実装していることです。Derefトレイトにより、スマートポインタ構造体のインスタンスは、 参照のように振る舞うことができるので、参照あるいはスマートポインタのどちらとも動作するコードを書くことができます。 Dropトレイトにより、スマートポインタのインスタンスがスコープを外れた時に走るコードをカスタマイズすることができます。 この章では、どちらのトレイトについても議論し、これらのトレイトがスマートポインタにとって重要な理由を説明します。

スマートポインタパターンがRustにおいてよく使われる一般的なデザインパターンだとして、この章では、全ての既存のスマートポインタを講義しません。 多くのライブラリに独自のスマートポインタがあり、自分だけのスマートポインタを書くことさえできます。 標準ライブラリの最もありふれたスマートポインタを講義します:

  • ヒープに値を確保するBox<T>
  • 複数の所有権を可能にする参照カウント型のRc<T>
  • RefCell<T>を通してアクセスされ、コンパイル時ではなく実行時に借用ルールを強制する型のRef<T>RefMut<T>

さらに、不変な型が、内部の値を可変化するAPIを晒す内部可変性パターンについても講義します。 また、循環参照についても議論します: 循環参照により、メモリがリークする方法とそれを回避する方法です。

さあ、飛び込みましょう!