<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Memory Management on kenji.blog</title><link>http://kenji.blog/id/tags/memory-management/</link><description>Recent content in Memory Management on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>id</language><copyright>kenjinote</copyright><lastBuildDate>Sat, 12 Sep 2026 07:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/id/tags/memory-management/index.xml" rel="self" type="application/rss+xml"/><item><title>Panduan Memanfaatkan Smart Pointer (std::unique_ptr / shared_ptr) untuk Mencegah Kebocoran Memori</title><link>http://kenji.blog/id/p/cpp-smart-pointers-guide-unique-shared-ptr/</link><pubDate>Sat, 12 Sep 2026 07:00:00 +0900</pubDate><guid>http://kenji.blog/id/p/cpp-smart-pointers-guide-unique-shared-ptr/</guid><description>&lt;img src="http://kenji.blog/p/cpp-smart-pointers-guide-unique-shared-ptr/img/eyecatch.jpg" alt="Featured image of post Panduan Memanfaatkan Smart Pointer (std::unique_ptr / shared_ptr) untuk Mencegah Kebocoran Memori" />&lt;p>Manajemen memori dalam C++ telah menjadi salah satu tantangan terbesar bagi pengembang selama bertahun-tahun. Gaya manajemen memori tradisional yang bergantung pada &lt;code>new&lt;/code> dan &lt;code>delete&lt;/code> secara manual merupakan sarang bagi bug yang serius, seperti kebocoran memori (memory leak), pointer yang menggantung (dangling pointer), dan pembebasan ganda (double free). Namun, dengan munculnya Modern C++ (C++11 dan seterusnya), situasinya telah berubah secara drastis. Inti dari perubahan ini adalah &amp;ldquo;Smart Pointer&amp;rdquo;.&lt;/p>
&lt;p>Dalam artikel ini, kami akan menjelaskan dengan sangat mendetail mekanisme dan panduan pemanfaatan tingkat lanjut dari &lt;code>std::unique_ptr&lt;/code>, &lt;code>std::shared_ptr&lt;/code>, dan &lt;code>std::weak_ptr&lt;/code> yang merupakan alat yang ampuh untuk memberantas kebocoran memori dan mewujudkan manajemen sumber daya yang aman serta efisien. Penjelasan ini akan mencakup implementasi internal (control block dan operasi atomik), dampaknya pada performa, serta perumusan penghitungan referensi (reference counting) menggunakan model matematika.&lt;/p>
&lt;h2 id="1-pendahuluan-zaman-kegelapan-manajemen-memori-c-dan-awal-mula-modern-c">1. Pendahuluan: Zaman Kegelapan Manajemen Memori C++ dan Awal Mula Modern C++
&lt;/h2>&lt;p>Dalam pengembangan C++ di masa lalu, memori yang dialokasikan pada heap harus dibebaskan oleh pengembang itu sendiri.&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-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="kt">void&lt;/span> &lt;span class="nf">legacy_function&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">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">some_condition&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">return&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// Terjadi kebocoran memori! delete tidak dipanggil
&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 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 class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Pada kode seperti di atas, jika pengecualian (exception) terjadi atau pengembalian lebih awal (early return) dilakukan, &lt;code>delete&lt;/code> akan dilewati dan kebocoran memori pun terjadi. Paradigma untuk mencegah hal ini disebut &amp;ldquo;RAII (Resource Acquisition Is Initialization)&amp;rdquo;. RAII adalah sebuah teknik yang mengikat perolehan sumber daya ke inisialisasi objek (konstruktor), dan pembebasan sumber daya ke penghancuran objek (destruktor). Smart pointer adalah kumpulan kelas pustaka standar yang mengaplikasikan idiom RAII ini pada manajemen memori.&lt;/p>
&lt;h2 id="2-stdunique_ptr-kepemilikan-eksklusif-dengan-nol-overhead-zero-overhead">2. &lt;code>std::unique_ptr&lt;/code>: Kepemilikan Eksklusif dengan Nol Overhead (Zero Overhead)
&lt;/h2>&lt;p>&lt;code>std::unique_ptr&lt;/code> adalah smart pointer yang memiliki &amp;ldquo;Kepemilikan Eksklusif (Exclusive Ownership)&amp;rdquo; atas objek yang dialokasikan secara dinamis. Hanya ada satu &lt;code>unique_ptr&lt;/code> pada satu waktu yang dapat memiliki suatu sumber daya.&lt;/p>
&lt;h3 id="21-prinsip-nol-overhead">2.1 Prinsip Nol Overhead
&lt;/h3>&lt;p>Daya tarik terbesar dari &lt;code>std::unique_ptr&lt;/code> adalah performanya. Dalam keadaan default tanpa kustom deleter, ukuran &lt;code>std::unique_ptr&lt;/code> sepenuhnya sama dengan pointer mentah (Raw Pointer). Tidak memiliki variabel anggota (member variables) yang tidak perlu, dan fungsi virtual juga tidak digunakan. Melalui pengoptimalan kompilator, akses melalui &lt;code>std::unique_ptr&lt;/code> dikembangkan menjadi kode assembly yang setara dengan pointer mentah.&lt;/p>
&lt;h3 id="22-perpindahan-kepemilikan-dan-stdmove">2.2 Perpindahan Kepemilikan dan &lt;code>std::move&lt;/code>
&lt;/h3>&lt;p>Karena memiliki kepemilikan eksklusif, &lt;code>std::unique_ptr&lt;/code> tidak dapat disalin (copy constructor dan copy assignment operator telah di-&lt;code>delete&lt;/code>). Untuk memindahkan kepemilikan ke &lt;code>unique_ptr&lt;/code> lain, Anda menggunakan &lt;code>std::move&lt;/code> untuk memanfaatkan Semantik Perpindahan (Move Semantics).&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;span class="lnt">26
&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">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">Resource&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">public&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Resource&lt;/span>&lt;span class="p">()&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">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Resource acquired&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">&amp;#34;&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="o">~&lt;/span>&lt;span class="n">Resource&lt;/span>&lt;span class="p">()&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">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Resource destroyed&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">&amp;#34;&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">void&lt;/span> &lt;span class="nf">do_something&lt;/span>&lt;span class="p">()&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">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Doing something&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">&amp;#34;&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="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">process_resource&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">Resource&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">ptr&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">do_something&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Saat keluar dari cakupan (scope), ptr dihancurkan, dan Resource juga dibebaskan
&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="n">unique_ptr&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">Resource&lt;/span>&lt;span class="o">&amp;gt;&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">Resource&lt;/span>&lt;span class="o">&amp;gt;&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">// process_resource(my_ptr); // Error: 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">process_resource&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 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="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">!&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;my_ptr is now empty.&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">&amp;#34;&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 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>Diagram Mermaid di bawah ini menunjukkan konsep perpindahan kepemilikan oleh &lt;code>std::move&lt;/code>.&lt;/p>
&lt;div class="mermaid">graph LR
subgraph "Sebelum std::move"
A["unique_ptr (ptr1)"] -->|"Memiliki"| B["Memori Heap (Objek)"]
end
subgraph "Setelah std::move"
C["unique_ptr (ptr1)"] -.->|"Kosong (nullptr)"| D["nullptr"]
E["unique_ptr (ptr2)"] -->|"Memiliki"| F["Memori Heap (Objek)"]
end&lt;/div>
&lt;h3 id="23-implementasi-kustom-deleter-custom-deleter">2.3 Implementasi Kustom Deleter (Custom Deleter)
&lt;/h3>&lt;p>Saat membungkus API warisan (legacy) dari bahasa C (misalnya &lt;code>FILE*&lt;/code> atau soket), Anda perlu memanggil fungsi selain &lt;code>delete&lt;/code> (seperti &lt;code>fclose&lt;/code>) untuk membebaskan memori. &lt;code>std::unique_ptr&lt;/code> memungkinkan Anda menentukan kustom deleter pada argumen template kedua.&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-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;cstdio&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">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Functor untuk kustom deleter
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">struct&lt;/span> &lt;span class="nc">FileDeleter&lt;/span> &lt;span class="p">{&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">operator&lt;/span>&lt;span class="p">()(&lt;/span>&lt;span class="n">FILE&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">fp&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">fp&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;Closing file.&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">&amp;#34;&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">fclose&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fp&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 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="k">using&lt;/span> &lt;span class="n">UniqueFile&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">unique_ptr&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">FILE&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">FileDeleter&lt;/span>&lt;span class="o">&amp;gt;&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">UniqueFile&lt;/span> &lt;span class="n">file&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">fopen&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;test.txt&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;w&amp;#34;&lt;/span>&lt;span class="p">));&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">file&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">fputs&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;Hello, Smart Pointers!&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">file&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">get&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 class="c1">// Saat cakupan berakhir, FileDeleter dipanggil dan fclose dieksekusi
&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>Menggunakan pointer fungsi atau ekspresi lambda sebagai kustom deleter berpotensi meningkatkan ukuran &lt;code>unique_ptr&lt;/code>, tetapi jika Anda menggunakan objek fungsi tanpa status (Functor) seperti di atas, ukurannya tidak akan bertambah dari pointer mentah berkat &lt;strong>EBCO (Empty Base Class Optimization)&lt;/strong> di C++ atau atribut &lt;code>[[no_unique_address]]&lt;/code> di C++20 (Nol overhead tetap dipertahankan).&lt;/p>
&lt;h2 id="3-stdshared_ptr-kepemilikan-bersama-shared-ownership-dan-control-block">3. &lt;code>std::shared_ptr&lt;/code>: Kepemilikan Bersama (Shared Ownership) dan Control Block
&lt;/h2>&lt;p>&lt;code>std::shared_ptr&lt;/code> adalah smart pointer yang memungkinkan beberapa pointer untuk berbagi kepemilikan atas objek yang sama. Ketika &lt;code>shared_ptr&lt;/code> yang terakhir dihancurkan, objek yang dikelola akan dibebaskan.&lt;/p>
&lt;h3 id="31-arsitektur-internal-control-block">3.1 Arsitektur Internal: Control Block
&lt;/h3>&lt;p>Secara terpisah dari pointer ke objek yang dikelola, &lt;code>std::shared_ptr&lt;/code> mengalokasikan dan berbagi metadata yang disebut &lt;strong>Control Block&lt;/strong> di heap. Control Block ini berisi informasi berikut:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Strong Count (Jumlah Referensi Kuat)&lt;/strong>: Jumlah &lt;code>shared_ptr&lt;/code> yang memiliki objek. Ketika nilainya mencapai 0, objek akan dihancurkan.&lt;/li>
&lt;li>&lt;strong>Weak Count (Jumlah Referensi Lemah)&lt;/strong>: Jumlah &lt;code>weak_ptr&lt;/code> yang memantau objek. Ketika baik Strong Count maupun Weak Count mencapai 0, Control Block itu sendiri akan dibebaskan.&lt;/li>
&lt;li>&lt;strong>Kustom Deleter dan Alokator&lt;/strong> (jika ditentukan).&lt;/li>
&lt;/ol>
&lt;div class="mermaid">graph TD
A["std::shared_ptr&lt;T> (sp1)"] -->|"Pointer ke T"| B["Objek yang Dikelola (T)"]
A -->|"Pointer ke Control Block"| C["Control Block"]
D["std::shared_ptr&lt;T> (sp2)"] -->|"Pointer ke T"| B
D -->|"Pointer ke Control Block"| C
C -->|"Menghapus"| B
C -.->|"Strong Count: 2"| E["Strong Count"]
C -.->|"Weak Count: 0"| F["Weak Count"]
C -.->|"Kustom Deleter"| G["Deleter"]&lt;/div>
&lt;p>Oleh karena itu, ukuran objek &lt;code>std::shared_ptr&lt;/code> itu sendiri biasanya dua kali lipat dari pointer mentah (pointer ke objek, dan pointer ke Control Block).&lt;/p>
&lt;h3 id="32-performa-dan-operasi-atomik">3.2 Performa dan Operasi Atomik
&lt;/h3>&lt;p>Penghitungan referensi (reference count) di dalam Control Block diimplementasikan sebagai &lt;strong>Operasi Atomik (Atomic Operations)&lt;/strong> sehingga penambahan dan pengurangannya dapat dilakukan secara aman bahkan dalam lingkungan multithread.&lt;/p>
&lt;p>Pada arsitektur x86/x64, instruksi atomik seperti &lt;code>lock xadd&lt;/code> digunakan untuk menambah atau mengurangi jumlah referensi. Hal ini melibatkan overhead sebesar puluhan siklus dibandingkan dengan penambahan bilangan bulat biasa. Oleh karena itu, meneruskan &lt;code>shared_ptr&lt;/code> ke sebuah fungsi melalui &lt;em>pass-by-value&lt;/em> akan menyebabkan penambahan dan pengurangan atomik setiap kali salinan dibuat, sehingga menurunkan performa.&lt;/p>
&lt;p>&lt;strong>Praktik Terbaik (Best Practice)&lt;/strong>: Saat meneruskan &lt;code>shared_ptr&lt;/code> ke suatu fungsi, kecuali jika Anda perlu berbagi kepemilikan, Anda sebaiknya meneruskannya sebagai &lt;code>const std::shared_ptr&amp;lt;T&amp;gt;&amp;amp;&lt;/code> (referensi const) atau meneruskan pointer/referensi mentahnya.&lt;/p>
&lt;h3 id="33-stdmake_shared-vs-new">3.3 &lt;code>std::make_shared&lt;/code> vs &lt;code>new&lt;/code>
&lt;/h3>&lt;p>Saat membuat &lt;code>shared_ptr&lt;/code>, Anda harus menggunakan &lt;code>std::make_shared&lt;/code> sedapat mungkin. Ada dua alasan penting untuk hal ini:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Pengoptimalan Alokasi Memori&lt;/strong>:
Menggunakan &lt;code>new&lt;/code> akan menyebabkan dua kali alokasi heap: satu untuk badan objek dan satu untuk control block. Dengan &lt;code>std::make_shared&lt;/code>, Anda dapat mengalokasikan satu blok memori besar yang mencakup keduanya dalam sekali alokasi heap, sehingga meningkatkan efisiensi cache.&lt;/li>
&lt;li>&lt;strong>Keamanan Pengecualian (Exception Safety)&lt;/strong>:
Dalam standar sebelum C++17, urutan evaluasi argumen fungsi belum ditentukan. Karena itu, jika terjadi pengecualian selama evaluasi argumen lain sebelum pointer yang dialokasikan oleh &lt;code>new&lt;/code> diteruskan ke konstruktor &lt;code>shared_ptr&lt;/code>, ada risiko kebocoran memori. &lt;code>make_shared&lt;/code> sepenuhnya menghindari masalah ini.&lt;/li>
&lt;/ol>
&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;/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">// Cara penulisan yang harus dihindari (2 kali alokasi memori)
&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">shared_ptr&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">MyClass&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">ptr1&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">new&lt;/span> &lt;span class="n">MyClass&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">// Cara penulisan yang disarankan (1 kali alokasi memori)
&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">shared_ptr&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">MyClass&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">ptr2&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_shared&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">MyClass&lt;/span>&lt;span class="o">&amp;gt;&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;h2 id="4-stdweak_ptr-menyelesaikan-siklus-referensi-circular-reference-dan-pemantauan">4. &lt;code>std::weak_ptr&lt;/code>: Menyelesaikan Siklus Referensi (Circular Reference) dan Pemantauan
&lt;/h2>&lt;p>Kepemilikan bersama memiliki kelemahan fatal yang disebut &amp;ldquo;Siklus Referensi (Circular References)&amp;rdquo;. Jika Objek A dan Objek B saling menunjuk satu sama lain dengan &lt;code>shared_ptr&lt;/code>, nilai Strong Count dari masing-masing objek akan dipertahankan setidaknya 1 dan tidak akan pernah mencapai 0 sampai program berakhir, sehingga terjadi kebocoran memori.&lt;/p>
&lt;div class="mermaid">graph TD
subgraph "Siklus Referensi (Kebocoran Memori)"
A["Objek A"] -->|"shared_ptr (Strong=1)"| B["Objek B"]
B -->|"shared_ptr (Strong=1)"| A
end&lt;/div>
&lt;h3 id="41-memutus-siklus-dengan-stdweak_ptr">4.1 Memutus Siklus dengan &lt;code>std::weak_ptr&lt;/code>
&lt;/h3>&lt;p>Alat yang dapat memecahkan masalah ini adalah &lt;code>std::weak_ptr&lt;/code>. &lt;code>weak_ptr&lt;/code> dibuat dari &lt;code>shared_ptr&lt;/code> dan merujuk pada objek, namun &lt;strong>tidak meningkatkan nilai Strong Count&lt;/strong>. Sebagai gantinya, ia akan menambah Weak Count. Dengan demikian, Anda dapat &amp;ldquo;memantau&amp;rdquo; suatu objek tanpa memiliki kepemilikan atasnya.&lt;/p>
&lt;div class="mermaid">graph TD
subgraph "Memutus Siklus Referensi"
C["Objek A"] -->|"shared_ptr (Strong=1)"| D["Objek B"]
D -.->|"weak_ptr (Weak=1)"| C
end&lt;/div>
&lt;h3 id="42-akses-aman-melalui-metode-lock">4.2 Akses Aman Melalui Metode &lt;code>lock()&lt;/code>
&lt;/h3>&lt;p>&lt;code>weak_ptr&lt;/code> tidak memiliki operator (&lt;code>-&amp;gt;&lt;/code> atau &lt;code>*&lt;/code>) untuk mengakses objek secara langsung. Hal ini dikarenakan ada kemungkinan objek target sudah dihancurkan. Untuk mengaksesnya dengan aman, Anda memanggil metode &lt;code>lock()&lt;/code> agar bisa memperoleh &lt;code>shared_ptr&lt;/code> sementara.&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;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&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">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">Node&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">public&lt;/span>&lt;span class="o">:&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">string&lt;/span> &lt;span class="n">name&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">shared_ptr&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">Node&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">next&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">weak_ptr&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">Node&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">prev&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// Menggunakan weak_ptr untuk mencegah siklus referensi
&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="n">Node&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&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;amp;&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">n&lt;/span>&lt;span class="p">)&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">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Created &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">name&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">&amp;#34;&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="o">~&lt;/span>&lt;span class="n">Node&lt;/span>&lt;span class="p">()&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">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Destroyed &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">name&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">&amp;#34;&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="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">nodeA&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_shared&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">Node&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;A&amp;#34;&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">nodeB&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_shared&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">Node&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;B&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="n">nodeA&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">next&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">nodeB&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">nodeB&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">prev&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">nodeA&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 shared_ptr dari weak_ptr lalu mengaksesnya
&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="k">auto&lt;/span> &lt;span class="n">locked_prev&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">nodeB&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">prev&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">lock&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;Node B&amp;#39;s prev is &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">locked_prev&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">name&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">&amp;#34;&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;Node B&amp;#39;s prev is already destroyed.&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">&amp;#34;&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="k">return&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// nodeA dan nodeB dihancurkan dengan benar
&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;h2 id="5-batasan-kepemilikan-bersama-dalam-lingkungan-multithread">5. Batasan Kepemilikan Bersama dalam Lingkungan Multithread
&lt;/h2>&lt;p>Keamanan thread (thread-safety) pada &lt;code>shared_ptr&lt;/code> sering kali disalahpahami. &amp;ldquo;Pembaruan pada jumlah referensi di dalam Control Block adalah thread-safe&amp;rdquo;, tetapi &amp;ldquo;proses baca/tulis dari objek &lt;code>shared_ptr&lt;/code> itu sendiri tidaklah thread-safe&amp;rdquo;.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Operasi yang aman&lt;/strong>: Beberapa thread membaca dan menulis instans &lt;code>shared_ptr&lt;/code> &lt;em>milik mereka masing-masing&lt;/em> (meskipun berbagai instans ini membagikan Control Block yang sama).&lt;/li>
&lt;li>&lt;strong>Data Race (Bahaya)&lt;/strong>: Beberapa thread melakukan proses baca/tulis terhadap instans &lt;code>shared_ptr&lt;/code> yang &lt;em>benar-benar sama&lt;/em> secara bersamaan.&lt;/li>
&lt;/ul>
&lt;p>Jika instans yang sama perlu dibagikan ke beberapa thread, Anda harus menggunakan &lt;code>std::atomic&amp;lt;std::shared_ptr&amp;lt;T&amp;gt;&amp;gt;&lt;/code> (C++20) atau melindunginya menggunakan mutex (&lt;code>std::mutex&lt;/code>).&lt;/p>
&lt;h2 id="6-perumusan-penghitungan-referensi-secara-matematika">6. Perumusan Penghitungan Referensi Secara Matematika
&lt;/h2>&lt;p>Transisi status dari siklus hidup di dalam Control Block dapat dinyatakan secara matematis sebagai berikut.
Misalkan Strong Count pada waktu $t$ adalah $S(t)$, dan Weak Count adalah $W(t)$.&lt;/p>
&lt;p>Status awal (tepat setelah &lt;code>make_shared&lt;/code>):
&lt;/p>
$$ S(0) = 1, \quad W(0) = 0 $$
&lt;p>Ketika salinan (replikasi &lt;code>shared_ptr&lt;/code>) dibuat:
&lt;/p>
$$ S(t_{next}) = S(t) + 1 $$
&lt;p>Kondisi di mana Objek yang Dikelola (Managed Object) dihancurkan:
&lt;/p>
$$ \lim_{t \to t_d} S(t) = 0 $$
&lt;p>Kondisi di mana Control Block itu sendiri dibebaskan dari memori:
&lt;/p>
$$ S(t) = 0 \quad \land \quad W(t) = 0 $$
&lt;p>
Dengan kata lain,
&lt;/p>
$$ S(t) + W(t) = 0 $$
&lt;p>Seperti yang ditunjukkan oleh rumus ini, selama &lt;code>weak_ptr&lt;/code> terus ada ($W(t) > 0$), memori kecil yang dialokasikan untuk Control Block akan tetap dipertahankan meskipun objek yang dikelolanya telah dihancurkan. Ini adalah satu-satunya kekurangan dari &lt;code>make_shared&lt;/code> pada kasus-kasus tertentu (karena memori objek yang dikelola terintegrasi dengan Control Block, maka ruang memori yang besar dari objek tersebut tidak akan dikembalikan ke sistem jika referensi lemahnya masih tersisa). Akan tetapi, pada umumnya manfaat dari segi performa yang diberikan oleh &lt;code>make_shared&lt;/code> jauh lebih unggul.&lt;/p>
&lt;h2 id="7-kesimpulan">7. Kesimpulan
&lt;/h2>&lt;p>Manajemen memori dalam Modern C++ tidak lagi berada di era di mana kita harus mengelola &lt;code>new&lt;/code>/&lt;code>delete&lt;/code> secara manual.&lt;/p>
&lt;ol>
&lt;li>Secara default, selalu gunakan &lt;strong>&lt;code>std::unique_ptr&lt;/code>&lt;/strong>, untuk mendapatkan keuntungan dari nol overhead sembari mengintegrasikan kepemilikan yang jelas ke dalam rancangan (desain).&lt;/li>
&lt;li>Gunakan &lt;strong>&lt;code>std::shared_ptr&lt;/code>&lt;/strong> hanya ketika benar-benar diperlukan adanya pembagian siklus hidup di antara beberapa pemilik, dan gunakan &lt;code>std::make_shared&lt;/code> untuk membuatnya.&lt;/li>
&lt;li>Dalam struktur data yang mungkin memunculkan lingkaran pembagian (siklus referensi) atau saat mengimplementasikan Observer Pattern, manfaatkan &lt;strong>&lt;code>std::weak_ptr&lt;/code>&lt;/strong> untuk mencegah kebocoran memori sejak dini.&lt;/li>
&lt;/ol>
&lt;p>Dengan memahami smart pointer secara mendalam dan memanfaatkannya di tempat yang tepat, Anda dapat membangun arsitektur perangkat lunak yang aman dan tangguh tanpa sedikit pun mengorbankan performa dari C++.&lt;/p></description></item></channel></rss>