<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Ownership on kenji.blog</title><link>http://kenji.blog/tags/ownership/</link><description>Recent content in Ownership on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>ja</language><copyright>kenjinote</copyright><lastBuildDate>Sat, 12 Sep 2026 04:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/tags/ownership/index.xml" rel="self" type="application/rss+xml"/><item><title>Rustの「所有権」と「借用」をC++のポインタと比較して解説</title><link>http://kenji.blog/p/rust-ownership-borrowing-cpp-pointer-comparison/</link><pubDate>Sat, 12 Sep 2026 04:00:00 +0900</pubDate><guid>http://kenji.blog/p/rust-ownership-borrowing-cpp-pointer-comparison/</guid><description>&lt;img src="http://kenji.blog/p/rust-ownership-borrowing-cpp-pointer-comparison/img/eyecatch.jpg" alt="Featured image of post Rustの「所有権」と「借用」をC++のポインタと比較して解説" />&lt;p>現代のシステムプログラミングにおいて、パフォーマンスとメモリ安全性の両立は永遠の課題です。C++は長年この分野の王者として君臨してきましたが、近年その地位を脅かしつつあるのがRustです。Rustの最大の特徴は、ガベージコレクション（GC）を持たずにメモリ安全性をコンパイル時に保証する「所有権（Ownership）」と「借用（Borrowing）」という概念にあります。&lt;/p>
&lt;p>本記事では、C++のポインタ（生ポインタ、&lt;code>std::unique_ptr&lt;/code>、&lt;code>std::shared_ptr&lt;/code>）とRustの所有権モデルを詳細に比較し、Rustのコンパイラ（ボローチェッカー）がどのようにしてUse-After-Free（解放後使用）やデータ競合（Data Race）を防いでいるのかを、コード例や図式を交えて徹底的に解説します。&lt;/p>
&lt;h2 id="1-メモリ管理の基礎スタックとヒープ">1. メモリ管理の基礎：スタックとヒープ
&lt;/h2>&lt;p>メモリ管理の基本を理解するために、まずはプログラムがメモリをどのように利用するかを振り返りましょう。メモリ領域は大きく分けて「スタック（Stack）」と「ヒープ（Heap）」に分類されます。&lt;/p>
&lt;h3 id="スタックstack">スタック（Stack）
&lt;/h3>&lt;p>関数呼び出し時のローカル変数などが積まれる領域です。LIFO（後入れ先出し）の構造を持ち、メモリの確保・解放が非常に高速です。コンパイル時にサイズが決定できるデータのみが配置されます。&lt;/p>
&lt;h3 id="ヒープheap">ヒープ（Heap）
&lt;/h3>&lt;p>実行時に動的にサイズが決まるデータや、関数のスコープを超えて生存する必要があるデータが配置されます。ポインタ（または参照）を通じてアクセスされます。&lt;/p>
&lt;p>ガベージコレクションを持たないC++やRustでは、ヒープメモリの管理コストを数式として以下のようにモデル化できます。オブジェクトの総数を $N$、アロケーションにかかる平均時間を $T_{alloc}$、デアロケーションにかかる平均時間を $T_{dealloc}$ とすると、メモリ管理の総コスト $C_{memory}$ は：&lt;/p>
$$ C_{memory} = \sum_{i=1}^{N} (T_{alloc, i} + T_{dealloc, i}) + O_{sync} $$
&lt;p>ここで $O_{sync}$ はマルチスレッド環境下での排他制御（ミューテックスやアトミック操作）にかかるオーバーヘッドです。Rustはコンパイル時にメモリ解放のタイミングを決定するため、実行時のガベージコレクションによるスループット低下（Stop-The-World）をゼロにしつつ、$T_{dealloc}$ を確実かつ安全なタイミングで実行します。&lt;/p>
&lt;div class="mermaid">graph TD
A["Program Memory"] --> B["Stack (Fast, Fixed Size)"]
A --> C["Heap (Dynamic, Slower)"]
B --> D["Local Variables"]
B --> E["Pointers/References"]
C --> F["Dynamically Allocated Data"]
E -.->|"Points to"| F&lt;/div>
&lt;h2 id="2-cのポインタ自由と危険のトレードオフ">2. C++のポインタ：自由と危険のトレードオフ
&lt;/h2>&lt;p>C++におけるメモリ管理の変遷を見てみましょう。&lt;/p>
&lt;h3 id="生ポインタraw-pointersの時代と問題点">生ポインタ（Raw Pointers）の時代と問題点
&lt;/h3>&lt;p>C言語から引き継がれた生ポインタ（&lt;code>*&lt;/code>）は、究極の自由を提供しますが、同時に以下のような深刻なバグの温床となります。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>メモリリーク（Memory Leak）&lt;/strong>: &lt;code>new&lt;/code>したメモリを&lt;code>delete&lt;/code>し忘れる。&lt;/li>
&lt;li>&lt;strong>Dangling Pointer（ダングリングポインタ）&lt;/strong>: メモリ解放後（&lt;code>delete&lt;/code>後）のポインタにアクセスする。&lt;/li>
&lt;li>&lt;strong>Double Free（二重解放）&lt;/strong>: 同じメモリ領域を2回&lt;code>delete&lt;/code>してしまう。&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// C++: 生ポインタによる問題の例
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="kt">void&lt;/span> &lt;span class="nf">rawPointerExample&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">int&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">ptr&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">new&lt;/span> &lt;span class="kt">int&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// ... 何らかの処理 ...
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">delete&lt;/span> &lt;span class="n">ptr&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 誤って再度アクセス (Use-After-Free / Dangling Pointer)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// C++コンパイラはこれをコンパイルエラーにできない
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">ptr&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// 未定義動作（Undefined Behavior）
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="raiiとスマートポインタの登場-c11以降">RAIIとスマートポインタの登場 (C++11以降)
&lt;/h3>&lt;p>C++11以降、RAII (Resource Acquisition Is Initialization) の概念に基づくスマートポインタが標準化され、生ポインタの直接利用は非推奨となりました。&lt;/p>
&lt;h4 id="stdunique_ptr">&lt;code>std::unique_ptr&lt;/code>
&lt;/h4>&lt;p>所有権が単一であることを表現するポインタです。スコープを抜けると自動的にメモリが解放されます。コピーはできず、所有権の「移動（ムーブ）」のみが可能です（&lt;code>std::move&lt;/code>を使用）。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// C++: std::unique_ptr
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;memory&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kt">void&lt;/span> &lt;span class="nf">uniquePtrExample&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">unique_ptr&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">int&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">p1&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">make_unique&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">int&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">42&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// std::unique_ptr&amp;lt;int&amp;gt; p2 = p1; // コンパイルエラー（コピー不可）
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">unique_ptr&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">int&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">p3&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">move&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">p1&lt;/span>&lt;span class="p">);&lt;/span> &lt;span class="c1">// 所有権の移動
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// C++の弱点：ムーブ後のp1はnullptrになるが、アクセス自体はコンパイル可能
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// 実行時にクラッシュ（セグメンテーションフォールト）を引き起こす
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// std::cout &amp;lt;&amp;lt; *p1 &amp;lt;&amp;lt; std::endl;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h4 id="stdshared_ptr">&lt;code>std::shared_ptr&lt;/code>
&lt;/h4>&lt;p>複数のポインタが同じオブジェクトを共有できるポインタです。参照カウント（Reference Counting）を用いて、カウントが0になった時点でメモリを解放します。アトミックな増減操作が必要なため、若干のパフォーマンスオーバーヘッド（前述の $O_{sync}$ に相当）が生じます。&lt;/p>
&lt;h2 id="3-rustの所有権ownershipパラダイムシフト">3. Rustの所有権（Ownership）：パラダイムシフト
&lt;/h2>&lt;p>Rustは、C++の&lt;code>std::unique_ptr&lt;/code>の概念を言語仕様の根幹に据え、さらに厳密にした「所有権モデル」を持っています。&lt;/p>
&lt;h3 id="所有権の3つのルール">所有権の3つのルール
&lt;/h3>&lt;p>Rustの所有権システムは、以下の3つの極めてシンプルなルールに基づいています。&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Rustの個々の値は、所有者（owner）と呼ばれる変数を持つ。&lt;/strong>&lt;/li>
&lt;li>&lt;strong>いかなる時も所有者は一つである。&lt;/strong>&lt;/li>
&lt;li>&lt;strong>所有者がスコープから外れたら、値は破棄される。&lt;/strong>&lt;/li>
&lt;/ol>
&lt;p>Rustではデフォルトでリソースは「ムーブ」されます。C++のように&lt;code>std::move&lt;/code>を明示しなくても、代入操作によって所有権が移動します。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-rust" data-lang="rust">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Rust: 所有権の移動（ムーブ）
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">fn&lt;/span> &lt;span class="nf">main&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="kd">let&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">s1&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nb">String&lt;/span>::&lt;span class="n">from&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;hello&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c1">// ヒープに確保されるデータ
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kd">let&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">s2&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">s1&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c1">// 所有権がs1からs2に移動（ムーブ）する
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c1">// C++と異なる最大の点：ムーブ後の変数へのアクセスは「コンパイルエラー」になる！
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c1">// println!(&amp;#34;{}, world!&amp;#34;, s1); // コンパイルエラー: value borrowed here after move
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>この「ムーブ後の変数をコンパイル時にアクセス不可にする」機能こそが、RustがC++の&lt;code>std::unique_ptr&lt;/code>よりも安全である理由の一つです。&lt;/p>
&lt;div class="mermaid">sequenceDiagram
participant S1 as "Variable s1"
participant Heap as "Heap Memory ('hello')"
participant S2 as "Variable s2"
S1->>Heap: "Allocates &amp; Owns"
Note over S1,S2: "let s2 = s1;"
S1--xHeap: "Loses Ownership (Invalidated)"
S2->>Heap: "Takes Ownership"&lt;/div>
&lt;h2 id="4-借用borrowingと参照">4. 借用（Borrowing）と参照
&lt;/h2>&lt;p>所有権を常に移動させていると、関数に値を渡すたびに所有権を返しもらわなければならず、非常に不便です。そこで登場するのが「借用（Borrowing）」です。C++のポインタや参照に相当します。&lt;/p>
&lt;p>Rustにおける借用には2つの種類があります。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>不変参照（Immutable Reference）&lt;/strong>: &lt;code>&amp;amp;T&lt;/code> （C++の &lt;code>const T&amp;amp;&lt;/code> に近い）&lt;/li>
&lt;li>&lt;strong>可変参照（Mutable Reference）&lt;/strong>: &lt;code>&amp;amp;mut T&lt;/code> （C++の &lt;code>T&amp;amp;&lt;/code> に近い）&lt;/li>
&lt;/ul>
&lt;h3 id="ボローチェッカーborrow-checkerの冷酷なる掟">ボローチェッカー（Borrow Checker）の冷酷なる掟
&lt;/h3>&lt;p>Rustのコンパイラには、参照の正当性を検証する「ボローチェッカー」が内蔵されています。ボローチェッカーは以下の厳格なルールを強制します。&lt;/p>
&lt;blockquote>
&lt;p>任意のスコープにおいて、以下のいずれか一方のみが存在可能である。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>1つの可変参照（&lt;code>&amp;amp;mut T&lt;/code>）&lt;/strong>&lt;/li>
&lt;li>&lt;strong>複数の不変参照（&lt;code>&amp;amp;T&lt;/code>）&lt;/strong>&lt;/li>
&lt;/ul>
&lt;/blockquote>
&lt;p>これは &lt;strong>「Multiple Readers XOR Single Writer (MRSW)」&lt;/strong> と呼ばれる原則です。数学の排他的論理和（XOR）で表現でき、状態 $S$ に対して、不変参照の数 $N_r$ と可変参照の数 $N_w$ は以下の制約を満たさなければなりません。&lt;/p>
$$ (N_r \ge 0 \land N_w = 0) \oplus (N_r = 0 \land N_w = 1) $$
&lt;p>このルールにより、&lt;strong>データ競合（Data Race）をコンパイル時に完全に排除&lt;/strong>します。データ競合は、①2つ以上のポインタが同じデータに同時アクセスし、②少なくとも1つが書き込みを行い、③同期メカニズムがない場合に発生します。Rustは②の条件をコンパイル時に破壊することでデータ競合を未然に防ぎます。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-rust" data-lang="rust">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Rust: 借用のルール違反によるコンパイルエラー
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">fn&lt;/span> &lt;span class="nf">main&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="kd">let&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">mut&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">s&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nb">String&lt;/span>::&lt;span class="n">from&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;hello&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="kd">let&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">r1&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">s&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c1">// 不変借用 (OK)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kd">let&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">r2&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">s&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c1">// 不変借用 (OK)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c1">// let r3 = &amp;amp;mut s; // エラー！不変借用が存在するのに可変借用は作れない
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="fm">println!&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="si">{}&lt;/span>&lt;span class="s">, &lt;/span>&lt;span class="si">{}&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">r1&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">r2&lt;/span>&lt;span class="p">);&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="5-イテレータ無効化iterator-invalidationの防止">5. イテレータ無効化（Iterator Invalidation）の防止
&lt;/h2>&lt;p>ボローチェッカーの威力が最も発揮される具体的な例として、「イテレータ無効化」という古典的なバグを見てみましょう。&lt;/p>
&lt;h3 id="cにおけるイテレータ無効化実行時クラッシュ">C++におけるイテレータ無効化（実行時クラッシュ）
&lt;/h3>&lt;p>C++の&lt;code>std::vector&lt;/code>をループ中に変更すると、背後のメモリが再確保（Reallocation）される可能性があり、参照がダングリングポインタと化します。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// C++: イテレータ無効化のバグ
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;vector&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kt">int&lt;/span> &lt;span class="nf">main&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">int&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">v&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// ベクタの要素への参照を取得
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">int&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">first&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">v&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">];&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 要素を追加（ここで容量が不足すると新しいメモリ領域が確保され、
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// 古い領域は破棄される可能性がある）
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">v&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">push_back&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">4&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// firstはすでに解放されたメモリを指している可能性がある！（未定義動作）
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;The first element is: &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">first&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="rustによるコンパイル時防御">Rustによるコンパイル時防御
&lt;/h3>&lt;p>全く同じロジックをRustで記述してみましょう。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-rust" data-lang="rust">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Rust: イテレータ無効化をコンパイル時に防ぐ
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">fn&lt;/span> &lt;span class="nf">main&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="kd">let&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">mut&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">v&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="fm">vec!&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="p">];&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c1">// 不変参照を取得 (借用開始)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kd">let&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">first&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">v&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">];&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c1">// エラー！ `first`が`v`を不変借用している間は、
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c1">// `v.push`に必要な可変借用を行うことはできない。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c1">// v.push(4);
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="fm">println!&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;The first element is: &lt;/span>&lt;span class="si">{}&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">first&lt;/span>&lt;span class="p">);&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>このように、Rustでは「値を読み取っている最中（不変借用中）に、その値を変更する（可変借用する）こと」がコンパイラレベルで禁止されているため、Use-After-Freeやイテレータ無効化といった致命的なバグがコンパイル時に確実に捕捉されます。&lt;/p>
&lt;div class="mermaid">graph LR
A["Variable v (Owner)"] --> B["Heap Array [1, 2, 3]"]
C["Reference 'first' (&amp;v[0])"] -.->|"Immutable Borrow"| B
A -->|X "Mutable Borrow Denied!"| D["v.push(4)"]
style C stroke:#00FF00,stroke-width:2px
style D stroke:#FF0000,stroke-width:2px&lt;/div>
&lt;h2 id="6-rustにおける共有所有権rc-と-arc">6. Rustにおける共有所有権：&lt;code>Rc&lt;/code> と &lt;code>Arc&lt;/code>
&lt;/h2>&lt;p>C++の&lt;code>std::shared_ptr&lt;/code>に相当する共有所有権もRustには用意されていますが、シングルスレッド用とマルチスレッド用に明確に型が分かれています。&lt;/p>
&lt;h3 id="シングルスレッド用rct-reference-counted">シングルスレッド用：&lt;code>Rc&amp;lt;T&amp;gt;&lt;/code> (Reference Counted)
&lt;/h3>&lt;p>&lt;code>Rc&amp;lt;T&amp;gt;&lt;/code>は、非スレッドセーフな参照カウントスマートポインタです。アトミックな命令を使わずにカウントを増減させるため、単一スレッド内では非常に高速です。しかし、これを別スレッドに送ろうとすると、コンパイルエラーになります（&lt;code>Send&lt;/code>トレイトを実装していないため）。&lt;/p>
&lt;h3 id="マルチスレッド用arct-atomic-reference-counted">マルチスレッド用：&lt;code>Arc&amp;lt;T&amp;gt;&lt;/code> (Atomic Reference Counted)
&lt;/h3>&lt;p>スレッド間で共有する場合は、アトミックな増減を行う&lt;code>Arc&amp;lt;T&amp;gt;&lt;/code>を使用します。C++の&lt;code>std::shared_ptr&lt;/code>と同等のコストがかかります。&lt;/p>
&lt;p>さらに、C++では&lt;code>std::shared_ptr&lt;/code>で共有している変数に対して、複数のスレッドから同時に書き込みを行うとデータ競合が発生します。これを防ぐためには&lt;code>std::mutex&lt;/code>を手動で正しく使う必要があります。&lt;/p>
&lt;p>一方Rustでは、&lt;code>Arc&amp;lt;T&amp;gt;&lt;/code>単体では&lt;strong>内部のデータを変更することができません&lt;/strong>。変更が必要な場合は、ミューテックスである&lt;code>Mutex&amp;lt;T&amp;gt;&lt;/code>と組み合わせる必要があります。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-rust" data-lang="rust">&lt;span class="line">&lt;span class="cl">&lt;span class="k">use&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">std&lt;/span>::&lt;span class="n">sync&lt;/span>::&lt;span class="p">{&lt;/span>&lt;span class="n">Arc&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Mutex&lt;/span>&lt;span class="p">};&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="k">use&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">std&lt;/span>::&lt;span class="n">thread&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="k">fn&lt;/span> &lt;span class="nf">main&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c1">// スレッドセーフな共有と排他制御の組み合わせ
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c1">// C++の std::shared_ptr&amp;lt;std::mutex&amp;gt; に近いが、Mutexがデータを内包している
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kd">let&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">counter&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Arc&lt;/span>::&lt;span class="n">new&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Mutex&lt;/span>::&lt;span class="n">new&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">));&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="kd">let&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">mut&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">handles&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="fm">vec!&lt;/span>&lt;span class="p">[];&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">for&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">_&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">in&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="o">..&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="kd">let&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">counter_clone&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Arc&lt;/span>::&lt;span class="n">clone&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">counter&lt;/span>&lt;span class="p">);&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="kd">let&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">handle&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">thread&lt;/span>::&lt;span class="n">spawn&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">move&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">||&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c1">// lock()を呼び出して初めて内部の可変参照(&amp;amp;mut i32)を得られる
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kd">let&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">mut&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">num&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">counter_clone&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">lock&lt;/span>&lt;span class="p">().&lt;/span>&lt;span class="n">unwrap&lt;/span>&lt;span class="p">();&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="n">num&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">+=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">});&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c1">// ロックの解放はRAIIによりスコープを抜けると自動で行われる
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">handles&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">push&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">handle&lt;/span>&lt;span class="p">);&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">for&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">handle&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">in&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">handles&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">handle&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">().&lt;/span>&lt;span class="n">unwrap&lt;/span>&lt;span class="p">();&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="fm">println!&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;Result: &lt;/span>&lt;span class="si">{}&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="n">counter&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">lock&lt;/span>&lt;span class="p">().&lt;/span>&lt;span class="n">unwrap&lt;/span>&lt;span class="p">());&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>特筆すべきは、Rustの&lt;code>Mutex&amp;lt;T&amp;gt;&lt;/code>は単なるロック機構ではなく、**「守るべきデータを型として内包している」**点です。これにより、「ロックを取り忘れてデータにアクセスする」というミスをコンパイルレベルで完全に防ぐことができます。ロック（&lt;code>lock()&lt;/code>）を取得しない限り、中身のデータへのアクセス権（参照）を得られない仕組みになっているのです。&lt;/p>
&lt;h2 id="まとめコンパイラによる事前検査か開発者による自己責任か">まとめ：コンパイラによる「事前検査」か、開発者による「自己責任」か
&lt;/h2>&lt;p>C++のポインタやスマートポインタは、開発者に高度な制御とパフォーマンスを提供しますが、その正しい利用は開発者の規律に依存しています。RAIIや&lt;code>std::unique_ptr&lt;/code>の導入によりC++は劇的に安全になりましたが、それでもムーブ後のアクセスやイテレータ無効化といった「未定義動作」を言語レベルで完全に防ぐことはできません。&lt;/p>
&lt;p>一方Rustは、所有権（Ownership）と借用（Borrowing）というルールをコンパイラに組み込むことで、これらのエラーを実行時ではなく&lt;strong>コンパイル時&lt;/strong>に検出します。「コンパイルが通るなら、メモリ安全である」という強い保証こそが、Rustがシステムプログラミングにおいて急速に支持を集めている最大の理由です。&lt;/p>
&lt;p>Rustのボローチェッカーと戦う（Fight the borrow checker）ことは、初学者にとって大きな壁となりますが、それは本来C++プログラマが頭の中で行っていた「ポインタの生存期間の追跡」という複雑な計算を、コンパイラが厳密に代行してくれているに過ぎません。&lt;/p>
&lt;p>C++のポインタの自由さと危険性を理解した上でRustを学ぶと、所有権モデルの背後にある「なぜこの設計になったのか」という哲学がより深く理解できるはずです。&lt;/p>
&lt;hr>
&lt;p>&lt;em>本記事は、C++とRustのメモリ管理手法についての比較考察です。各プロジェクトの要件に応じて適切な言語を選択するための参考になれば幸いです。&lt;/em>&lt;/p></description></item></channel></rss>