<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Rust on kenji.blog</title><link>http://kenji.blog/id/categories/rust/</link><description>Recent content in Rust on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>id</language><copyright>kenjinote</copyright><lastBuildDate>Sat, 12 Sep 2026 04:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/id/categories/rust/index.xml" rel="self" type="application/rss+xml"/><item><title>Penjelasan tentang "Kepemilikan" dan "Peminjaman" di Rust dibandingkan dengan Pointer di C++</title><link>http://kenji.blog/id/p/rust-ownership-borrowing-cpp-pointer-comparison/</link><pubDate>Sat, 12 Sep 2026 04:00:00 +0900</pubDate><guid>http://kenji.blog/id/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 Penjelasan tentang "Kepemilikan" dan "Peminjaman" di Rust dibandingkan dengan Pointer di C++" />&lt;p>Dalam pemrograman sistem modern, menyeimbangkan kinerja dan keamanan memori adalah tantangan abadi. C++ telah berkuasa sebagai raja di bidang ini selama bertahun-tahun, tetapi dalam beberapa tahun terakhir, posisinya mulai terancam oleh Rust. Fitur terbesar Rust terletak pada konsep &amp;ldquo;Kepemilikan&amp;rdquo; (Ownership) dan &amp;ldquo;Peminjaman&amp;rdquo; (Borrowing), yang menjamin keamanan memori pada saat kompilasi tanpa memiliki garbage collection (GC).&lt;/p>
&lt;p>Pada artikel ini, kita akan membandingkan secara rinci pointer C++ (pointer mentah, &lt;code>std::unique_ptr&lt;/code>, &lt;code>std::shared_ptr&lt;/code>) dan model kepemilikan Rust, serta menjelaskan secara menyeluruh bagaimana kompiler Rust (borrow checker) mencegah Use-After-Free (penggunaan setelah pembebasan) dan data race (perlombaan data), disertai dengan contoh kode dan diagram.&lt;/p>
&lt;h2 id="1-dasar-dasar-manajemen-memori-stack-dan-heap">1. Dasar-dasar Manajemen Memori: Stack dan Heap
&lt;/h2>&lt;p>Untuk memahami dasar-dasar manajemen memori, mari kita tinjau kembali bagaimana sebuah program menggunakan memori. Area memori secara umum dibagi menjadi &amp;ldquo;Stack&amp;rdquo; dan &amp;ldquo;Heap&amp;rdquo;.&lt;/p>
&lt;h3 id="stack">Stack
&lt;/h3>&lt;p>Ini adalah area di mana variabel lokal saat pemanggilan fungsi dan sejenisnya ditumpuk. Ini memiliki struktur LIFO (Last-In-First-Out) dan alokasi/de-alokasi memorinya sangat cepat. Hanya data yang ukurannya dapat ditentukan pada saat kompilasi yang ditempatkan di sini.&lt;/p>
&lt;h3 id="heap">Heap
&lt;/h3>&lt;p>Data yang ukurannya ditentukan secara dinamis pada saat runtime, atau data yang perlu bertahan melampaui ruang lingkup (scope) fungsi ditempatkan di sini. Data ini diakses melalui pointer (atau referensi).&lt;/p>
&lt;p>Dalam C++ atau Rust yang tidak memiliki garbage collection, biaya manajemen memori heap dapat dimodelkan dalam rumus matematika sebagai berikut. Misalkan jumlah total objek adalah $N$, waktu rata-rata yang diperlukan untuk alokasi adalah $T_{alloc}$, dan waktu rata-rata yang diperlukan untuk de-alokasi adalah $T_{dealloc}$, maka total biaya manajemen memori $C_{memory}$ adalah:&lt;/p>
$$ C_{memory} = \sum_{i=1}^{N} (T_{alloc, i} + T_{dealloc, i}) + O_{sync} $$
&lt;p>Di sini, $O_{sync}$ adalah overhead untuk kontrol eksklusif (seperti mutex atau operasi atomik) di bawah lingkungan multi-thread. Karena Rust menentukan waktu pembebasan memori pada saat kompilasi, penurunan throughput akibat garbage collection (Stop-The-World) pada saat runtime menjadi nol, sementara $T_{dealloc}$ dieksekusi pada waktu yang pasti dan aman.&lt;/p>
&lt;div class="mermaid">graph TD
A["Memori Program"] --> B["Stack (Cepat, Ukuran Tetap)"]
A --> C["Heap (Dinamis, Lebih Lambat)"]
B --> D["Variabel Lokal"]
B --> E["Pointer/Referensi"]
C --> F["Data yang Dialokasikan Secara Dinamis"]
E -.->|"Menunjuk ke"| F&lt;/div>
&lt;h2 id="2-pointer-c-pertukaran-antara-kebebasan-dan-bahaya">2. Pointer C++: Pertukaran antara Kebebasan dan Bahaya
&lt;/h2>&lt;p>Mari kita lihat evolusi manajemen memori di C++.&lt;/p>
&lt;h3 id="era-pointer-mentah-raw-pointers-dan-masalahnya">Era Pointer Mentah (Raw Pointers) dan Masalahnya
&lt;/h3>&lt;p>Pointer mentah (&lt;code>*&lt;/code>) yang diwarisi dari bahasa C menawarkan kebebasan tertinggi, tetapi pada saat yang sama menjadi sarang bagi bug serius seperti berikut.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Kebocoran Memori (Memory Leak)&lt;/strong>: Lupa menggunakan &lt;code>delete&lt;/code> pada memori yang dialokasikan dengan &lt;code>new&lt;/code>.&lt;/li>
&lt;li>&lt;strong>Dangling Pointer&lt;/strong>: Mengakses pointer setelah memorinya dibebaskan (setelah &lt;code>delete&lt;/code>).&lt;/li>
&lt;li>&lt;strong>Double Free&lt;/strong>: Menggunakan &lt;code>delete&lt;/code> dua kali pada area memori yang sama.&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++: Contoh masalah dengan pointer mentah
&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">// ... beberapa proses ...
&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">// Mengakses kembali secara tidak sengaja (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">// Kompiler C++ tidak dapat membuat ini menjadi kesalahan kompilasi
&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">// Perilaku Tidak Terdefinisi (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="kemunculan-raii-dan-smart-pointer-sejak-c11">Kemunculan RAII dan Smart Pointer (Sejak C++11)
&lt;/h3>&lt;p>Sejak C++11, smart pointer berdasarkan konsep RAII (Resource Acquisition Is Initialization) telah distandardisasi, dan penggunaan langsung pointer mentah sudah tidak disarankan.&lt;/p>
&lt;h4 id="stdunique_ptr">&lt;code>std::unique_ptr&lt;/code>
&lt;/h4>&lt;p>Ini adalah pointer yang mengekspresikan bahwa kepemilikannya tunggal. Memori secara otomatis dibebaskan saat keluar dari scope. Itu tidak dapat disalin, dan hanya kepemilikan yang dapat &amp;ldquo;dipindahkan&amp;rdquo; (move) (menggunakan &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; // Kesalahan kompilasi (tidak dapat disalin)
&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">// Perpindahan kepemilikan
&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">// Kelemahan C++: p1 menjadi nullptr setelah pemindahan, tetapi aksesnya sendiri dapat dikompilasi
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// Ini akan menyebabkan crash saat runtime (segmentation fault)
&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>Ini adalah pointer yang memungkinkan beberapa pointer untuk berbagi objek yang sama. Ia menggunakan penghitungan referensi (Reference Counting), dan membebaskan memori ketika hitungannya mencapai 0. Karena operasi penambahan/pengurangan atomik diperlukan, ini menyebabkan sedikit overhead kinerja (setara dengan $O_{sync}$ yang disebutkan sebelumnya).&lt;/p>
&lt;h2 id="3-kepemilikan-ownership-rust-perubahan-paradigma">3. Kepemilikan (Ownership) Rust: Perubahan Paradigma
&lt;/h2>&lt;p>Rust menjadikan konsep &lt;code>std::unique_ptr&lt;/code> dari C++ sebagai inti dari spesifikasi bahasanya, dan memiliki &amp;ldquo;model kepemilikan&amp;rdquo; yang bahkan lebih ketat.&lt;/p>
&lt;h3 id="3-aturan-kepemilikan">3 Aturan Kepemilikan
&lt;/h3>&lt;p>Sistem kepemilikan Rust didasarkan pada tiga aturan yang sangat sederhana berikut:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Setiap nilai dalam Rust memiliki variabel yang disebut pemiliknya (owner).&lt;/strong>&lt;/li>
&lt;li>&lt;strong>Hanya boleh ada satu pemilik pada satu waktu.&lt;/strong>&lt;/li>
&lt;li>&lt;strong>Ketika pemilik keluar dari scope, nilai tersebut akan dibuang.&lt;/strong>&lt;/li>
&lt;/ol>
&lt;p>Di Rust, sumber daya &amp;ldquo;dipindahkan&amp;rdquo; secara default. Bahkan tanpa menyebutkan &lt;code>std::move&lt;/code> secara eksplisit seperti di C++, operasi penugasan memindahkan kepemilikan.&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: Perpindahan kepemilikan (Move)
&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">// Data yang dialokasikan di heap
&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">// Kepemilikan berpindah (move) dari s1 ke 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">// Perbedaan terbesar dengan C++: Akses ke variabel setelah perpindahan menjadi &amp;#34;kesalahan kompilasi&amp;#34;!
&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); // Kesalahan kompilasi: 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>Fungsi &amp;ldquo;membuat variabel yang dipindahkan tidak dapat diakses pada saat kompilasi&amp;rdquo; ini adalah salah satu alasan mengapa Rust lebih aman daripada &lt;code>std::unique_ptr&lt;/code> di C++.&lt;/p>
&lt;div class="mermaid">sequenceDiagram
participant S1 as "Variabel s1"
participant Heap as "Memori Heap ('hello')"
participant S2 as "Variabel s2"
S1->>Heap: "Mengalokasikan &amp; Memiliki"
Note over S1,S2: "let s2 = s1;"
S1--xHeap: "Kehilangan Kepemilikan (Tidak Valid)"
S2->>Heap: "Mengambil Kepemilikan"&lt;/div>
&lt;h2 id="4-peminjaman-borrowing-dan-referensi">4. Peminjaman (Borrowing) dan Referensi
&lt;/h2>&lt;p>Jika kepemilikan selalu dipindahkan, kita harus mengembalikan kepemilikan setiap kali kita meneruskan nilai ke suatu fungsi, yang mana itu sangat tidak nyaman. Di sinilah &amp;ldquo;Peminjaman&amp;rdquo; (Borrowing) berperan. Ini setara dengan pointer atau referensi dalam C++.&lt;/p>
&lt;p>Ada dua jenis peminjaman di Rust:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Referensi Imutabel (Immutable Reference)&lt;/strong>: &lt;code>&amp;amp;T&lt;/code> (Mirip dengan &lt;code>const T&amp;amp;&lt;/code> dalam C++)&lt;/li>
&lt;li>&lt;strong>Referensi Mutabel (Mutable Reference)&lt;/strong>: &lt;code>&amp;amp;mut T&lt;/code> (Mirip dengan &lt;code>T&amp;amp;&lt;/code> dalam C++)&lt;/li>
&lt;/ul>
&lt;h3 id="aturan-kejam-dari-borrow-checker">Aturan Kejam dari Borrow Checker
&lt;/h3>&lt;p>Kompiler Rust memiliki mekanisme bawaan bernama &amp;ldquo;borrow checker&amp;rdquo; yang memvalidasi kebenaran referensi. Borrow checker memaksakan aturan ketat berikut:&lt;/p>
&lt;blockquote>
&lt;p>Dalam suatu scope tertentu, hanya salah satu dari berikut ini yang dapat ada:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Satu referensi mutabel (&lt;code>&amp;amp;mut T&lt;/code>)&lt;/strong>&lt;/li>
&lt;li>&lt;strong>Beberapa referensi imutabel (&lt;code>&amp;amp;T&lt;/code>)&lt;/strong>&lt;/li>
&lt;/ul>
&lt;/blockquote>
&lt;p>Ini disebut sebagai prinsip &lt;strong>&amp;ldquo;Multiple Readers XOR Single Writer (MRSW)&amp;rdquo;&lt;/strong>. Ini dapat diekspresikan dengan matematika XOR (Exclusive OR). Untuk status $S$, jumlah referensi imutabel $N_r$ dan jumlah referensi mutabel $N_w$ harus memenuhi batasan berikut:&lt;/p>
$$ (N_r \ge 0 \land N_w = 0) \oplus (N_r = 0 \land N_w = 1) $$
&lt;p>Melalui aturan ini, &lt;strong>data race sepenuhnya dihilangkan pada saat kompilasi&lt;/strong>. Data race terjadi ketika: (1) dua atau lebih pointer mengakses data yang sama secara bersamaan, (2) setidaknya satu darinya melakukan penulisan, dan (3) tidak ada mekanisme sinkronisasi. Rust mencegah data race agar tidak terjadi dengan menghancurkan kondisi (2) pada saat kompilasi.&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: Kesalahan kompilasi karena pelanggaran aturan peminjaman
&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">// Peminjaman imutabel (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">// Peminjaman imutabel (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; // Error! Tidak dapat membuat peminjaman mutabel jika ada peminjaman imutabel
&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-mencegah-inisialisasi-iterator-yang-tidak-valid-iterator-invalidation">5. Mencegah Inisialisasi Iterator yang Tidak Valid (Iterator Invalidation)
&lt;/h2>&lt;p>Sebagai contoh konkret di mana kekuatan borrow checker paling terlihat, mari kita lihat bug klasik yang disebut &amp;ldquo;pembatalan iterator&amp;rdquo; (iterator invalidation).&lt;/p>
&lt;h3 id="iterator-invalidation-di-c-crash-saat-runtime">Iterator Invalidation di C++ (Crash saat Runtime)
&lt;/h3>&lt;p>Jika kita memodifikasi &lt;code>std::vector&lt;/code> dalam C++ di dalam loop, memori di belakangnya dapat dialokasikan ulang (Reallocation), mengubah referensi menjadi dangling pointer.&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++: Bug invalidasi iterator
&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">// Mendapatkan referensi ke elemen vektor
&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">// Menambahkan elemen (Jika kapasitas tidak cukup di sini, area memori baru akan dialokasikan,
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// dan area lama mungkin dibuang)
&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 mungkin menunjuk ke memori yang sudah dibebaskan! (Perilaku Tidak Terdefinisi)
&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="pertahanan-saat-kompilasi-oleh-rust">Pertahanan saat Kompilasi oleh Rust
&lt;/h3>&lt;p>Mari kita tulis logika yang sama persis di 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: Mencegah invalidasi iterator pada saat kompilasi
&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">// Mendapatkan referensi imutabel (Peminjaman dimulai)
&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">// Error! Selama `first` meminjam `v` secara imutabel,
&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">// peminjaman mutabel yang diperlukan untuk `v.push` tidak dapat dilakukan.
&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>Seperti ini, di Rust, &amp;ldquo;mengubah suatu nilai (meminjam mutabel) saat nilai tersebut sedang dibaca (dipinjam imutabel)&amp;rdquo; dilarang pada tingkat kompiler, sehingga bug fatal seperti Use-After-Free atau pembatalan iterator pasti ditangkap pada saat kompilasi.&lt;/p>
&lt;div class="mermaid">graph LR
A["Variabel v (Pemilik)"] --> B["Array Heap [1, 2, 3]"]
C["Referensi 'first' (&amp;v[0])"] -.->|"Peminjaman Imutabel"| B
A -->|X "Peminjaman Mutabel Ditolak!"| D["v.push(4)"]
style C stroke:#00FF00,stroke-width:2px
style D stroke:#FF0000,stroke-width:2px&lt;/div>
&lt;h2 id="6-kepemilikan-bersama-di-rust-rc-dan-arc">6. Kepemilikan Bersama di Rust: &lt;code>Rc&lt;/code> dan &lt;code>Arc&lt;/code>
&lt;/h2>&lt;p>Kepemilikan bersama yang setara dengan &lt;code>std::shared_ptr&lt;/code> di C++ juga tersedia di Rust, namun tipenya dipisahkan dengan jelas untuk thread tunggal dan multi-thread.&lt;/p>
&lt;h3 id="untuk-thread-tunggal-rct-reference-counted">Untuk Thread Tunggal: &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> adalah smart pointer penghitung referensi yang tidak thread-safe. Ia sangat cepat di dalam satu thread tunggal karena menambah dan mengurangi hitungan tanpa menggunakan instruksi atomik. Namun, jika Anda mencoba mengirimnya ke thread lain, itu akan menyebabkan kesalahan kompilasi (karena tidak mengimplementasikan trait &lt;code>Send&lt;/code>).&lt;/p>
&lt;h3 id="untuk-multi-thread-arct-atomic-reference-counted">Untuk Multi-thread: &lt;code>Arc&amp;lt;T&amp;gt;&lt;/code> (Atomic Reference Counted)
&lt;/h3>&lt;p>Saat berbagi antar thread, kita menggunakan &lt;code>Arc&amp;lt;T&amp;gt;&lt;/code> yang melakukan penambahan dan pengurangan secara atomik. Biayanya setara dengan &lt;code>std::shared_ptr&lt;/code> di C++.&lt;/p>
&lt;p>Lebih jauh lagi, di C++, jika Anda melakukan penulisan secara bersamaan dari beberapa thread ke variabel yang dibagikan dengan &lt;code>std::shared_ptr&lt;/code>, data race akan terjadi. Untuk mencegah hal ini, Anda harus menggunakan &lt;code>std::mutex&lt;/code> dengan benar secara manual.&lt;/p>
&lt;p>Di sisi lain, dalam Rust, &lt;strong>data di dalam tidak dapat diubah&lt;/strong> hanya dengan &lt;code>Arc&amp;lt;T&amp;gt;&lt;/code> saja. Jika perubahan diperlukan, ia harus digabungkan dengan &lt;code>Mutex&amp;lt;T&amp;gt;&lt;/code>, yang merupakan sebuah mutex.&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">// Kombinasi dari pembagian thread-safe dan kontrol eksklusif
&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">// Mirip dengan std::shared_ptr&amp;lt;std::mutex&amp;gt; di C++, tetapi Mutex membungkus data
&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">// Referensi mutabel internal (&amp;amp;mut i32) hanya dapat diperoleh dengan memanggil lock()
&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">// Pembebasan kunci secara otomatis dilakukan oleh RAII saat keluar dari scope
&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>Yang perlu diperhatikan adalah &lt;code>Mutex&amp;lt;T&amp;gt;&lt;/code> di Rust bukan sekadar mekanisme penguncian, tetapi &lt;strong>&amp;ldquo;membungkus data yang harus dilindungi sebagai sebuah tipe&amp;rdquo;&lt;/strong>. Dengan ini, kesalahan seperti &amp;ldquo;mengakses data karena lupa mengambil kunci&amp;rdquo; dapat sepenuhnya dicegah pada tingkat kompilasi. Sistem dirancang sedemikian rupa sehingga hak akses (referensi) ke data di dalamnya tidak dapat diperoleh kecuali kunci (&lt;code>lock()&lt;/code>) telah didapatkan.&lt;/p>
&lt;h2 id="kesimpulan-pemeriksaan-sebelumnya-oleh-kompiler-atau-tanggung-jawab-sendiri-oleh-pengembang">Kesimpulan: &amp;ldquo;Pemeriksaan Sebelumnya&amp;rdquo; oleh Kompiler, atau &amp;ldquo;Tanggung Jawab Sendiri&amp;rdquo; oleh Pengembang?
&lt;/h2>&lt;p>Pointer dan smart pointer C++ menawarkan kontrol tingkat tinggi dan kinerja kepada para pengembang, tetapi penggunaannya yang benar bergantung pada disiplin pengembang. Meskipun C++ menjadi jauh lebih aman dengan diperkenalkannya RAII dan &lt;code>std::unique_ptr&lt;/code>, &amp;ldquo;perilaku tidak terdefinisi&amp;rdquo; seperti akses setelah perpindahan atau pembatalan iterator masih tidak dapat dicegah sepenuhnya pada tingkat bahasa.&lt;/p>
&lt;p>Di sisi lain, Rust mendeteksi kesalahan-kesalahan ini &lt;strong>pada saat kompilasi&lt;/strong> dan bukan saat runtime, dengan memasukkan aturan Kepemilikan (Ownership) dan Peminjaman (Borrowing) ke dalam kompiler. Jaminan kuat bahwa &amp;ldquo;jika dapat dikompilasi, maka memori aman&amp;rdquo; adalah alasan terbesar mengapa Rust dengan cepat mendapatkan dukungan dalam pemrograman sistem.&lt;/p>
&lt;p>Bertarung dengan borrow checker Rust (Fight the borrow checker) adalah rintangan besar bagi pemula, namun itu hanya kompiler yang dengan ketat mengambil alih perhitungan kompleks tentang &amp;ldquo;melacak masa pakai pointer&amp;rdquo; yang awalnya dilakukan di kepala oleh pemrogram C++.&lt;/p>
&lt;p>Mempelajari Rust setelah memahami kebebasan dan bahaya pointer C++ akan membantu Anda untuk lebih memahami secara mendalam filosofi &amp;ldquo;mengapa dirancang seperti ini&amp;rdquo; di balik model kepemilikan.&lt;/p>
&lt;hr>
&lt;p>&lt;em>Artikel ini adalah studi perbandingan metode manajemen memori di C++ dan Rust. Kami harap ini berfungsi sebagai referensi untuk memilih bahasa yang tepat berdasarkan persyaratan masing-masing proyek.&lt;/em>&lt;/p></description></item><item><title>Kelebihan dan Kekurangan yang Dirasakan Insinyur C++ Setelah Mempelajari Rust</title><link>http://kenji.blog/id/p/cpp-engineer-learning-rust-pros-cons/</link><pubDate>Sat, 12 Sep 2026 03:00:00 +0900</pubDate><guid>http://kenji.blog/id/p/cpp-engineer-learning-rust-pros-cons/</guid><description>&lt;img src="http://kenji.blog/p/cpp-engineer-learning-rust-pros-cons/img/eyecatch.jpg" alt="Featured image of post Kelebihan dan Kekurangan yang Dirasakan Insinyur C++ Setelah Mempelajari Rust" />&lt;h1 id="pendahuluan-fajar-baru-pemrograman-sistem">Pendahuluan: Fajar Baru Pemrograman Sistem
&lt;/h1>&lt;p>Dalam rekayasa perangkat lunak modern, C++ dan Rust berdiri di garis depan pemrograman sistem sebagai dua raksasa utama. Selama bertahun-tahun, C++ telah berkuasa sebagai raja mutlak di domain yang menuntut performa ekstrem dari perangkat keras, seperti sistem operasi, perangkat tertanam (embedded devices), mesin game (game engines), dan sistem perdagangan frekuensi tinggi (HFT). Saya sendiri sebagai insinyur C++ senior, mulai dari belantara pointer mentah di era C++98, melalui gelombang modernisasi C++11 (pengenalan smart pointer, lambda expressions, dan &lt;code>auto&lt;/code>), hingga mendampingi spesifikasi yang terus membengkak di C++14/17/20, telah terus menulis kode.&lt;/p>
&lt;p>Namun baru-baru ini, sebagai solusi untuk kelemahan struktural yang dimiliki C++—terutama kerentanan keamanan yang disebabkan oleh &amp;ldquo;kurangnya keamanan memori&amp;rdquo; (sekitar 70% dari CVE konon disebabkan oleh memori) dan &amp;ldquo;spesifikasi yang semakin kompleks tanpa akhir dan perilaku tidak terdefinisi (UB)&amp;quot;—Rust telah menunjukkan kebangkitan yang dramatis. Adopsi resminya ke dalam kernel Linux, serta proyek migrasi skala besar ke Rust oleh perusahaan-perusahaan teknologi raksasa seperti Microsoft, Google, dan AWS, bukanlah sekadar tren sementara, melainkan menandakan pergeseran paradigma dalam pemrograman sistem.&lt;/p>
&lt;p>Dalam artikel ini, dari sudut pandang teknis yang berkaitan erat dengan fondasi spesifikasi bahasa, saya akan membandingkan dan menjelaskan secara mendalam &amp;ldquo;kelebihan&amp;rdquo; dan &amp;ldquo;kekurangan&amp;rdquo; yang dirasakan oleh seorang insinyur C++ tulen setelah benar-benar mempelajari Rust secara mendalam dan menggunakannya dalam praktik.&lt;/p>
&lt;hr>
&lt;h1 id="1-pergeseran-paradigma-manajemen-memori-dari-raii-ke-kepemilikan-dan-peminjaman">1. Pergeseran Paradigma Manajemen Memori: Dari RAII ke Kepemilikan dan Peminjaman
&lt;/h1>&lt;h2 id="raii-pada-c-dan-keterbatasan-smart-pointer">RAII pada C++ dan Keterbatasan Smart Pointer
&lt;/h2>&lt;p>Salah satu penemuan terbesar C++ adalah &lt;strong>RAII (Resource Acquisition Is Initialization)&lt;/strong>. Konsep ini, di mana sumber daya dialokasikan di konstruktor dan dibebaskan secara otomatis di destruktor saat keluar dari cakupan (scope), telah membebaskan pengembang dari teror kebocoran memori akibat penggunaan &lt;code>new&lt;/code> dan &lt;code>delete&lt;/code> secara manual. Mulai C++11, &lt;code>std::unique_ptr&lt;/code> dan &lt;code>std::shared_ptr&lt;/code> diperkenalkan ke perpustakaan standar, memungkinkan konsep kepemilikan (Ownership) untuk diekspresikan dalam kode.&lt;/p>
&lt;p>Namun, smart pointer dan semantik perpindahan (move semantics) C++ memiliki kelemahan fatal di mana verifikasi statis oleh kompilator tidak sempurna.&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-cpp" data-lang="cpp">&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">#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;string&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">consume&lt;/span>&lt;span class="p">(&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="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">ptr&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">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Consuming: &amp;#34;&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>&lt;/span>&lt;span class="line">&lt;span class="cl">&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="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="k">auto&lt;/span> &lt;span class="n">my_ptr&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="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;Hello, C++&amp;#34;&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">// Memindahkan (move) kepemilikan ke fungsi
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">consume&lt;/span>&lt;span class="p">(&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">my_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">// Bahaya: Di C++, mengakses objek setelah di-move tidak menyebabkan error kompilasi
&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::move hanyalah sekadar cast ke rvalue reference (T&amp;amp;&amp;amp;), dan kompilator tidak memblokir penggunaannya
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">my_ptr&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">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Pointer is still valid?&amp;#34;&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 class="p">}&lt;/span> &lt;span class="k">else&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">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Pointer is null.&amp;#34;&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 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">// std::cout &amp;lt;&amp;lt; *my_ptr &amp;lt;&amp;lt; std::endl; // Perilaku tidak terdefinisi akibat penggunaan memori setelah dibebaskan (Use-After-Free)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &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;p>Di C++, selalu ada risiko bahwa Anda secara tidak sengaja mengakses objek yang isinya telah dikosongkan (valid tetapi dalam keadaan yang tidak ditentukan) oleh &lt;code>std::move&lt;/code>. Ini dapat langsung berujung pada crash saat runtime, atau dalam kasus terburuk, lubang keamanan.&lt;/p>
&lt;h2 id="kepemilikan-ownership-rust-dan-pertahanan-absolut-borrow-checker">Kepemilikan (Ownership) Rust dan Pertahanan Absolut Borrow Checker
&lt;/h2>&lt;p>Rust menggabungkan konsep &amp;ldquo;kepemilikan&amp;rdquo; ini ke dalam desain inti bahasanya, dan melakukan analisis statis yang ketat melalui fitur kompilator yang disebut &lt;strong>Borrow Checker (Pengecek Peminjaman)&lt;/strong>.&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="k">fn&lt;/span> &lt;span class="nf">consume&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">s&lt;/span>: &lt;span class="nb">String&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="fm">println!&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;Consuming: &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">s&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">// Di sini s keluar dari scope, dan memori dibebaskan (Drop)
&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="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">my_string&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, Rust&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="c1">// Memindahkan kepemilikan ke fungsi. Di Rust, default-nya adalah semantik move.
&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">consume&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">my_string&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">// Error kompilasi! Variabel setelah di-move sama sekali tidak bisa diakses
&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;Is it still there? {}&amp;#34;, my_string);
&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>Di Rust, pada saat kepemilikan sebuah variabel dipindahkan, variabel asli tersebut diperlakukan oleh kompilator setara dengan status &amp;ldquo;tidak diinisialisasi&amp;rdquo; dan sepenuhnya memblokir akses selanjutnya. Akibatnya, bug seperti &amp;ldquo;Use-After-Free (penggunaan memori setelah pembebasan)&amp;rdquo; dan &amp;ldquo;Dangling Pointer (pointer menggantung)&amp;rdquo; secara teoretis tidak akan dapat melewati kompilasi.&lt;/p>
&lt;div class="mermaid">graph TD
A["C++ std::unique_ptr"] --> B["std::move diterapkan"]
B --> C["Kepemilikan Dipindahkan"]
C --> D["Pointer Lama Masih Dapat Diakses"]
D --> E["Potensi Perilaku Tidak Terdefinisi (UB)"]
F["Rust Box / String"] --> G["Dilewatkan berdasarkan Nilai (Move)"]
G --> H["Kepemilikan Dipindahkan"]
H --> I["Kompilator Memblokir Variabel Lama"]
I --> J["Keamanan Memori Dijamin"]&lt;/div>
&lt;h2 id="peminjaman-borrowing-dan-kontrol-mutabilitas">Peminjaman (Borrowing) dan Kontrol Mutabilitas
&lt;/h2>&lt;p>Yang lebih kuat lagi adalah aturan &amp;ldquo;peminjaman (Borrowing)&amp;rdquo; yang merujuk pada sumber daya. Di Rust, aturan berikut ini dipaksakan:&lt;/p>
&lt;ol>
&lt;li>Pada waktu tertentu, &lt;strong>hanya satu dari keduanya&lt;/strong> yang boleh ada: &amp;ldquo;banyak referensi tidak dapat diubah (immutable reference, &lt;code>&amp;amp;T&lt;/code>)&amp;rdquo; ATAU &amp;ldquo;satu referensi yang dapat diubah (mutable reference, &lt;code>&amp;amp;mut T&lt;/code>)&amp;rdquo;.&lt;/li>
&lt;li>Referensi tidak boleh hidup lebih lama daripada scope data aslinya (batasan lifetime).&lt;/li>
&lt;/ol>
&lt;p>Di C++, sangat mudah untuk membuat beberapa referensi atau pointer yang mutable (dapat diubah) ke objek yang sama, dan ini memicu kerusakan status yang tidak terduga (seperti pembatalan iterator). Rust mencegah bug ini sejak awal dengan melarang kombinasi &amp;ldquo;Aliasing (penamaan alternatif) + Mutability (kemampuan diubah)&amp;rdquo; di tingkat bahasa.&lt;/p>
&lt;hr>
&lt;h1 id="2-tata-letak-memori-dan-overhead-matematis-smart-pointer">2. Tata Letak Memori dan Overhead Matematis Smart Pointer
&lt;/h1>&lt;p>Dalam pemrograman sistem, pemahaman yang akurat tentang tata letak memori sangatlah penting. Mari kita bandingkan &lt;code>std::shared_ptr&lt;/code> dari C++ dengan &lt;code>std::rc::Rc&lt;/code> / &lt;code>std::sync::Arc&lt;/code> dari Rust.&lt;/p>
&lt;p>&lt;code>std::shared_ptr&lt;/code> C++ mengelola sumber daya melalui penghitungan referensi, dan secara default menggunakan operasi atomik (&lt;code>std::atomic&lt;/code>) yang aman untuk thread (thread-safe) untuk menambah atau mengurangi jumlah referensi. Overhead pada memori tersebut dapat dirumuskan sebagai berikut:&lt;/p>
$$ Overhead_{C++} = sizeof(T) + sizeof(ControlBlock) $$
&lt;p>Di sini, $ControlBlock$ mencakup &amp;ldquo;Penghitung Referensi Kuat (Strong Ref Count)&amp;rdquo;, &amp;ldquo;Penghitung Referensi Lemah (Weak Ref Count)&amp;rdquo;, dan &amp;ldquo;Deleter Kustom (Custom Deleter)&amp;rdquo;. Masalahnya adalah, meskipun hanya digunakan dalam single-thread, overhead dari instruksi atomik (seperti penguncian baris cache, dll.) terjadi tanpa syarat.&lt;/p>
&lt;p>Sebaliknya, Rust secara tegas memisahkan smart pointer sesuai dengan tujuan penggunaannya.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Untuk Single-thread&lt;/strong>: &lt;code>Rc&amp;lt;T&amp;gt;&lt;/code> (Reference Counted)&lt;/li>
&lt;li>&lt;strong>Untuk Multi-thread&lt;/strong>: &lt;code>Arc&amp;lt;T&amp;gt;&lt;/code> (Atomic Reference Counted)&lt;/li>
&lt;/ul>
$$ Overhead_{Rc} = sizeof(T) + 2 \times sizeof(usize) $$
$$ Overhead_{Arc} = sizeof(T) + 2 \times sizeof(AtomicUsize) $$
&lt;p>Di Rust, jika menggunakan &lt;code>Rc&amp;lt;T&amp;gt;&lt;/code> yang khusus untuk single-thread, Anda dapat sepenuhnya menghindari penalti operasi atomik (abstraksi nol-biaya). Dan melalui mekanisme keselamatan thread (thread-safety) yang dijelaskan nanti, sistem tipe (type system) sepenuhnya mencegah kesalahan dalam memberikan &lt;code>Rc&amp;lt;T&amp;gt;&lt;/code> ke thread lain.&lt;/p>
&lt;hr>
&lt;h1 id="3-keselamatan-thread-kejutan-dari-fearless-concurrency">3. Keselamatan Thread: Kejutan dari &amp;ldquo;Fearless Concurrency&amp;rdquo;
&lt;/h1>&lt;p>Pemrograman multi-thread di C++ selalu berdampingan dengan ketakutan akan perlombaan data (data race) dan kebuntuan (deadlock).&lt;/p>
&lt;h2 id="bahaya-dari-pemisahan-mutex-dan-data-di-c">Bahaya dari Pemisahan Mutex dan Data di C++
&lt;/h2>&lt;p>&lt;code>std::mutex&lt;/code> pada C++ pada dasarnya hanyalah pengontrol eksklusif untuk &amp;ldquo;blok kode tertentu (critical section)&amp;rdquo;, dan tidak ada kaitan bahasawi antara &amp;ldquo;data yang harus dilindungi&amp;rdquo; dan &amp;ldquo;mutex&amp;rdquo;-nya.&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;/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="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;thread&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;mutex&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="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">shared_data&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">mutex&lt;/span> &lt;span class="n">mtx&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="kt">void&lt;/span> &lt;span class="nf">worker&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="c1">// Sekalipun pengembang lupa mendapatkan kunci (lock), proses kompilasi tetap akan lolos
&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::lock_guard&amp;lt;std::mutex&amp;gt; lock(mtx);
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">shared_data&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">1&lt;/span>&lt;span class="p">);&lt;/span> &lt;span class="c1">// Perlombaan data (data race) yang fatal!
&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;span class="line">&lt;span class="cl">
&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="kr">thread&lt;/span> &lt;span class="n">t1&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">worker&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="kr">thread&lt;/span> &lt;span class="n">t2&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">worker&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">t1&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">t2&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">();&lt;/span>
&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;h2 id="mutex-rust-memiliki-datanya">Mutex Rust &amp;ldquo;Memiliki&amp;rdquo; Datanya
&lt;/h2>&lt;p>Di Rust, &lt;code>Mutex&amp;lt;T&amp;gt;&lt;/code> menggunakan generik untuk &lt;strong>membungkus (memiliki)&lt;/strong> tipe data yang dilindunginya, &lt;code>T&lt;/code>. Untuk mengakses data, Anda diharuskan memanggil &lt;code>lock()&lt;/code> untuk mendapatkan objek pelindung (guard object). Menyentuh data tanpa mendapatkan kunci (lock) adalah hal yang tidak mungkin secara tata bahasa (sintaks).&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;/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">// Data sepenuhnya dienkapsulasi di dalam 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">shared_data&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="nb">Vec&lt;/span>::&lt;span class="n">new&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">2&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">// Mengkloning Arc (penghitungan referensi yang aman untuk thread) untuk dibagikan antar thread
&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">data_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">shared_data&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">// Tanpa mendapatkan kunci (lock), akses ke Vec internal tidak bisa dilakukan
&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">data&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">data_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="n">data&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">push&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>&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 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 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>Terlebih lagi, di dalam Rust terdapat 2 sifat inti (core traits) yang menjamin keamanan pemrosesan paralel.&lt;/p>
&lt;ul>
&lt;li>&lt;code>Send&lt;/code>: Tipe data yang kepemilikannya dapat ditransfer antar thread dengan aman&lt;/li>
&lt;li>&lt;code>Sync&lt;/code>: Tipe data yang aman jika diakses secara bersamaan oleh beberapa thread&lt;/li>
&lt;/ul>
&lt;p>Sebagai contoh, &lt;code>Rc&amp;lt;T&amp;gt;&lt;/code> yang tidak aman untuk thread tidak mengimplementasikan trait &lt;code>Send&lt;/code>. Oleh karena itu, jika Anda mencoba meneruskannya ke &lt;code>thread::spawn&lt;/code>, ini akan langsung menyebabkan error kompilasi. Dengan adanya &amp;ldquo;Fearless Concurrency (Konkurensi Tanpa Rasa Takut)&amp;rdquo; ini, pengembang terbebas dari ketakutan akan bug, dan dapat memajukan paralelisasi dengan jauh lebih agresif.&lt;/p>
&lt;p>Menurut Hukum Amdahl (Amdahl&amp;rsquo;s Law), throughput maksimum teoretis untuk bagian yang dapat diparalelkan $P$ dan derajat paralelisme $N$ dinyatakan sebagai berikut:&lt;/p>
$$ S(N) = \frac{1}{(1 - P) + \frac{P}{N}} $$
&lt;p>Rust memungkinkan dilakukannya refaktor untuk memaksimalkan $P$ ini dengan sangat aman, mengandalkan sistem tipe.&lt;/p>
&lt;div class="mermaid">graph TD
A["Keamanan Thread C++"] --> B["Bergantung pada Ingatan Pengembang"]
B --> C["Mutex Terpisah dari Data"]
C --> D["Risiko Tinggi Perlombaan Data Terselubung"]
E["Keamanan Thread Rust"] --> F["Trait Send dan Sync"]
F --> G["Mutex Memiliki Data"]
G --> H["Perlombaan Data Dicegah pada Waktu Kompilasi"]&lt;/div>
&lt;hr>
&lt;h1 id="4-penanganan-kesalahan-pengecualian-vs-tipe-data-aljabar">4. Penanganan Kesalahan: Pengecualian vs Tipe Data Aljabar
&lt;/h1>&lt;p>Standar penanganan kesalahan (error handling) di C++ adalah &amp;ldquo;Pengecualian (Exceptions)&amp;rdquo;. Namun, pengecualian membuat alur kontrol menjadi tidak jelas, dan menyebabkan penalti performa (seperti stack unwinding dan pembengkakan RTTI). Dalam sistem tertanam atau mesin game, menonaktifkan pengecualian sepenuhnya (&lt;code>-fno-exceptions&lt;/code>) dan mengadopsi desain yang mengembalikan kode kesalahan (error code) klasik sangat sering dilakukan. Meskipun &lt;code>std::expected&lt;/code> telah diperkenalkan pada C++23, dibutuhkan waktu bagi ekosistem secara keseluruhan untuk mengadopsinya.&lt;/p>
&lt;p>Di Rust, konsep pengecualian tidak ada. Kesalahan dikembalikan murni sebagai &amp;ldquo;nilai&amp;rdquo;, dan direpresentasikan menggunakan tipe enumerasi (tipe data aljabar) &lt;code>Result&amp;lt;T, E&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;/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">fs&lt;/span>::&lt;span class="n">File&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">io&lt;/span>::&lt;span class="p">{&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Read&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">// Hanya dengan melihat tipe nilai kembaliannya, jelas bahwa kesalahan IO dapat terjadi
&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">read_file_content&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">path&lt;/span>: &lt;span class="kp">&amp;amp;&lt;/span>&lt;span class="kt">str&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>-&amp;gt; &lt;span class="nb">Result&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="nb">String&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">io&lt;/span>::&lt;span class="n">Error&lt;/span>&lt;span class="o">&amp;gt;&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">// Dengan operator ?, return awal seketika jika error, dan jika sukses ekstrak isinya
&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">file&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">File&lt;/span>::&lt;span class="n">open&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">path&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">?&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">content&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">new&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">file&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">read_to_string&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="k">mut&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">content&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">?&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="nb">Ok&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">content&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>Operator &lt;code>?&lt;/code> ini revolusioner. Operator ini menghilangkan persarangan (nesting) dalam (piramida pernyataan if) yang terjadi saat memeriksa kode kesalahan di C++, mempertahankan alur kode yang bersih seperti pengecualian, sekaligus memungkinkan penulisan secara eksplisit pada panggilan fungsi mana kesalahan tersebut disebarkan (propagated).&lt;/p>
&lt;hr>
&lt;h1 id="5-polimorfisme-dari-fungsi-virtual-dan-templat-ke-trait">5. Polimorfisme: Dari Fungsi Virtual dan Templat ke Trait
&lt;/h1>&lt;p>Polimorfisme dalam C++ diimplementasikan terutama melalui pewarisan kelas dan dispatch dinamis dengan fungsi virtual (&lt;code>virtual&lt;/code>), atau dispatch statis menggunakan templat (seperti CRTP).&lt;/p>
&lt;p>Pada dispatch dinamis, pointer ke tabel fungsi virtual (vtable), yaitu vptr, tertanam ke dalam objek, menyebabkan terjadinya overhead akibat penyelesaian pointer saat pemanggilan fungsi.&lt;/p>
$$ T_{dispatch} = T_{lookup\_in\_vtable} + T_{dereference} $$
&lt;p>Rust membuang &amp;ldquo;pewarisan kelas&amp;rdquo; ala orientasi objek klasik dan sebagai gantinya mengadopsi konsep &amp;ldquo;&lt;strong>Traits&lt;/strong>&amp;rdquo; (ini mirip dengan Konsep/Concept C++20, namun jauh lebih kaya fitur).&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;/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">trait&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Drawable&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="k">fn&lt;/span> &lt;span class="nf">draw&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="bp">self&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">struct&lt;/span> &lt;span class="nc">Circle&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">radius&lt;/span>: &lt;span class="kt">f64&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">impl&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Drawable&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">for&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Circle&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="k">fn&lt;/span> &lt;span class="nf">draw&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="bp">self&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 class="fm">println!&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;Menggambar Lingkaran dengan jari-jari &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="bp">self&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">radius&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="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">// Dispatch Statis (Monomorfisasi / Nol Overhead)
&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">draw_static&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">T&lt;/span>: &lt;span class="nc">Drawable&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">item&lt;/span>: &lt;span class="kp">&amp;amp;&lt;/span>&lt;span class="nc">T&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="n">item&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">draw&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="c1">// Dispatch Dinamis (Objek Trait)
&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">draw_dynamic&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">item&lt;/span>: &lt;span class="kp">&amp;amp;&lt;/span>&lt;span class="nc">dyn&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Drawable&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="n">item&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">draw&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>Fitur terbesar dari dispatch dinamis Rust (&lt;code>dyn Trait&lt;/code>) adalah penggunaan &lt;strong>Fat Pointer&lt;/strong> alih-alih memiliki vptr di dalam struktur datanya. Fat Pointer menyimpan &amp;ldquo;pointer ke data&amp;rdquo; dan &amp;ldquo;pointer ke vtable&amp;rdquo; sebagai pasangan. Karena itu, sangat mudah untuk mengimplementasikan (memperluas) trait kemudian pada tipe yang didefinisikan oleh perpustakaan (library) eksternal untuk dipanggil secara dispatch dinamis.&lt;/p>
&lt;hr>
&lt;h1 id="6-manajemen-paket-dan-sistem-build-penderitaan-cmake-vs-karunia-cargo">6. Manajemen Paket dan Sistem Build: Penderitaan CMake vs Karunia Cargo
&lt;/h1>&lt;p>Salah satu kelemahan terbesar C++ adalah ketiadaan manajer paket (package manager) standar. Tata bahasa &lt;code>CMakeLists.txt&lt;/code> yang rumit, kompleksitas penyelesaian dependensi oleh &lt;code>find_package&lt;/code>, dan perbedaan pada jalur pustaka (library path) untuk setiap sistem operasi (OS) terus-menerus merampas banyak waktu dari insinyur C++.&lt;/p>
&lt;p>Rust hadir dengan standar &lt;strong>Cargo&lt;/strong>, yaitu gabungan antara manajer paket dan sistem build terbaik di dunia.&lt;/p>
&lt;div class="mermaid">graph TD
A["Lingkungan Build C++"] --> B["CMakeLists.txt"]
B --> C["Integrasi vcpkg / Conan"]
C --> D["Menghasilkan Makefiles / Ninja"]
D --> E["Kompilator (GCC/Clang/MSVC)"]
F["Lingkungan Build Rust"] --> G["Cargo.toml"]
G --> H["Mengambil dependensi dari crates.io"]
H --> I["rustc (Cargo build)"]
I --> J["Biner Siap Dijalankan"]&lt;/div>
&lt;p>Hanya dengan menambahkan satu baris nama dan versi dari pustaka dependensi (crate) ke &lt;code>Cargo.toml&lt;/code>, Cargo akan menangani semuanya secara otomatis mulai dari menyelesaikan dependensi transitif, pengunduhan, hingga kompilasi. Selanjutnya, semua rantai perkakas (toolchain) yang diperlukan untuk pengembangan seperti pengujian (&lt;code>cargo test&lt;/code>), pembuatan dokumentasi (&lt;code>cargo doc&lt;/code>), analisis statis (&lt;code>cargo clippy&lt;/code>), dan formatter (&lt;code>cargo fmt&lt;/code>), seluruhnya terintegrasi ke dalam satu perintah ini. Kenyamanan ini memiliki daya hancur yang sedemikian rupa sehingga begitu Anda mencicipinya, Anda tak akan mau kembali ke lingkungan build C++.&lt;/p>
&lt;hr>
&lt;h1 id="7-kekurangan-dan-kurva-pembelajaran-dalam-mempelajari-rust">7. Kekurangan dan Kurva Pembelajaran dalam Mempelajari Rust
&lt;/h1>&lt;p>Sejauh ini saya telah membicarakan tentang kelebihan Rust, tetapi &amp;ldquo;dinding&amp;rdquo; dan kekurangan yang pasti dihadapi oleh insinyur C++ ketika mencoba untuk menempatkan Rust ke dalam praktik pertempuran yang sesungguhnya tentu saja ada.&lt;/p>
&lt;h2 id="1-pergulatan-sengit-dengan-borrow-checker">1. Pergulatan Sengit dengan Borrow Checker
&lt;/h2>&lt;p>Jika Anda mencoba untuk secara langsung mengimplementasikan struktur data yang di C++ &amp;ldquo;biasanya dihubungkan dengan pointer mentah (raw pointer)&amp;rdquo; (seperti doubly linked list, struktur graf, atau struktur yang mereferensikan dirinya sendiri) ke dalam Rust, kode tersebut tidak akan lulus kompilasi karena adanya batasan pada kepemilikan dan lifetime. Untuk memuaskan Borrow Checker, Anda perlu menerapkan pembungkus yang rumit seperti &lt;code>Rc&amp;lt;RefCell&amp;lt;T&amp;gt;&amp;gt;&lt;/code>, atau secara fundamental merombak desain menjadi pengelolaan berbasis indeks atau menggunakan arena allocator.&lt;/p>
&lt;h2 id="2-lamanya-waktu-kompilasi">2. Lamanya Waktu Kompilasi
&lt;/h2>&lt;p>Meskipun kompilasi di C++ menjadi lambat karena templat yang bersarang (nested), waktu kompilasi Rust (terutama clean build dari nol) sama sekali tidak bisa dikatakan singkat. Karena tumpang tindih dari pass optimasi LLVM yang kuat, perluasan makro, dan monomorfisasi (monomorphization) dari generik, waktu build akan menjadi hambatan (bottleneck) dalam proyek skala besar. Selama masa pengembangan, berbagai trik seperti seringnya menggunakan &lt;code>cargo check&lt;/code> merupakan hal yang sangat penting.&lt;/p>
&lt;h2 id="3-interoperabilitas-dengan-basis-kode-c">3. Interoperabilitas dengan Basis Kode C++
&lt;/h2>&lt;p>Meskipun integrasi dengan bahasa C (FFI) sangat lancar, untuk mengintegrasikan Rust secara langsung dengan basis kode C++ yang ada dan sangat besar (yang banyak menggunakan kelas, templat, dan fungsi virtual) adalah hal yang sangat sulit. Baru-baru ini, alat jembatan seperti &lt;code>cxx&lt;/code> dan &lt;code>autocxx&lt;/code> memang telah berkembang, tetapi masih terdapat rintangan yang tinggi untuk mencapai transisi yang benar-benar mulus.&lt;/p>
&lt;hr>
&lt;h1 id="kesimpulan-haruskah-kita-bermigrasi-ke-rust">Kesimpulan: Haruskah Kita Bermigrasi ke Rust?
&lt;/h1>&lt;p>C++ di masa mendatang akan terus memainkan peran penting dalam pengembangan mesin game dan infrastruktur besar yang sudah ada. Modernisasi melalui C++20/23 juga sangat luar biasa, memungkinkannya untuk ditulis dengan cara yang jauh lebih aman.&lt;/p>
&lt;p>Namun, untuk &amp;ldquo;proyek pemrograman sistem yang baru dimulai,&amp;rdquo; saya merasa sekarang &lt;strong>lebih sulit menemukan alasan untuk TIDAK memilih Rust&lt;/strong>. &amp;ldquo;Kepastian (certainty)&amp;rdquo; yang ditawarkan oleh Rust, di mana selama kodenya lulus dikompilasi maka Anda terbebas dari ketakutan akan perilaku tidak terdefinisi dan kerusakan memori, serta kemampuan untuk memproses secara paralel dengan aman dan pada kinerja tinggi, secara dramatis meningkatkan model mental seorang insinyur.&lt;/p>
&lt;p>Bagi seorang insinyur C++, mempelajari Rust bukan sekadar tentang menghafal sintaksis baru, melainkan sebuah pengalaman terbaik untuk mendapatkan perspektif baru terhadap &amp;ldquo;metode pengelolaan memori dan thread yang aman&amp;rdquo;. Saya harap Anda semua juga dapat merasakan secara langsung nyamannya penggunaan Cargo sekaligus ketegasan yang diberikan oleh Borrow Checker.&lt;/p></description></item></channel></rss>