<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://program.sonsuz.us/feed.xml" rel="self" type="application/atom+xml" /><link href="https://program.sonsuz.us/" rel="alternate" type="text/html" /><updated>2026-10-23T06:05:42+00:00</updated><id>https://program.sonsuz.us/feed.xml</id><title type="html">SonsuzUs</title><subtitle>Programlama ve Yazılım</subtitle><author><name>Sonsuz Us</name></author><entry><title type="html">C++ Nesne Dilimlenmesi: Kopyalama Sırasında Kaybolan Kimlik</title><link href="https://program.sonsuz.us/posts/c-nesne-dilimlenmesi-kopyalama-sirasinda-kaybolan-kimlik/" rel="alternate" type="text/html" title="C++ Nesne Dilimlenmesi: Kopyalama Sırasında Kaybolan Kimlik" /><published>2026-10-23T00:00:00+00:00</published><updated>2026-10-23T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/c-nesne-dilimlenmesi-kopyalama-sirasinda-kaybolan-kimlik</id><content type="html" xml:base="https://program.sonsuz.us/posts/c-nesne-dilimlenmesi-kopyalama-sirasinda-kaybolan-kimlik/"><![CDATA[<p>C++’ta kalıtım kullanırken türetilmiş bir nesneyi temel sınıf türündeki değişkene değer olarak atamak ilk bakışta zararsız görünebilir. Kod derlenir, program çalışır ve çoğu zaman hata mesajı da alınmaz. Fakat bu işlem sırasında nesnenin yalnızca temel sınıfa ait bölümü kopyalanır; türetilmiş sınıfın eklediği veriler ve davranış kimliği kaybolur. İşte bu sessiz bilgi kaybına <strong>nesne dilimlenmesi</strong>, yani <em>object slicing</em> denir.</p>

<p>``</p>

<h2 id="nesne-neden-dilimlenir">Nesne neden “dilimlenir”?</h2>

<p>Bir türetilmiş sınıf nesnesini kavramsal olarak iki parçalı düşünebiliriz:</p>

\[Türetilmiş\ Nesne = Temel\ Bölüm + Türetilmiş\ Bölüm\]

<p>Temel sınıf türünde değer saklayan bir değişkenin kapasitesi ise yalnızca temel bölüme uygundur. Dolayısıyla aşağıdaki atamada <code class="language-plaintext highlighter-rouge">Calisan</code> nesnesinin <code class="language-plaintext highlighter-rouge">Yazilimci</code> sınıfına özgü kısmı hedef nesneye sığmaz. C++ bu kısmı hata vermeden dışarıda bırakır.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;string&gt;</span><span class="cp">
</span>
<span class="k">class</span> <span class="nc">Calisan</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">ad</span><span class="p">;</span>

    <span class="k">virtual</span> <span class="kt">void</span> <span class="n">tanit</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span>
        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">ad</span> <span class="o">&lt;&lt;</span> <span class="s">": Calisan</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">};</span>

<span class="k">class</span> <span class="nc">Yazilimci</span> <span class="o">:</span> <span class="k">public</span> <span class="n">Calisan</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">dil</span><span class="p">;</span>

    <span class="kt">void</span> <span class="n">tanit</span><span class="p">()</span> <span class="k">const</span> <span class="k">override</span> <span class="p">{</span>
        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">ad</span> <span class="o">&lt;&lt;</span> <span class="s">": "</span> <span class="o">&lt;&lt;</span> <span class="n">dil</span> <span class="o">&lt;&lt;</span> <span class="s">" gelistiricisi</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">};</span>

<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">Yazilimci</span> <span class="n">y</span><span class="p">;</span>
    <span class="n">y</span><span class="p">.</span><span class="n">ad</span> <span class="o">=</span> <span class="s">"Ada"</span><span class="p">;</span>
    <span class="n">y</span><span class="p">.</span><span class="n">dil</span> <span class="o">=</span> <span class="s">"C++"</span><span class="p">;</span>

    <span class="n">Calisan</span> <span class="n">c</span> <span class="o">=</span> <span class="n">y</span><span class="p">;</span> <span class="c1">// Nesne dilimlenir</span>
    <span class="n">c</span><span class="p">.</span><span class="n">tanit</span><span class="p">();</span>     <span class="c1">// Ada: Calisan</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">tanit()</code> sanal olmasına rağmen sonuç değişmez. Çünkü <code class="language-plaintext highlighter-rouge">c</code>, artık bağımsız ve gerçek bir <code class="language-plaintext highlighter-rouge">Calisan</code> nesnesidir. İçinde <code class="language-plaintext highlighter-rouge">Yazilimci</code> kimliği bulunmadığından sanal fonksiyon mekanizmasının çağırabileceği türetilmiş davranış da kalmamıştır. <code class="language-plaintext highlighter-rouge">virtual</code>, dilimlenmeyi önlemez; yalnızca nesneye referans veya işaretçi üzerinden erişildiğinde dinamik türü kullanır.</p>

<table>
  <thead>
    <tr>
      <th>Aktarım biçimi</th>
      <th style="text-align: right">Kopyalama var mı?</th>
      <th style="text-align: right">Türetilmiş bilgi korunur mu?</th>
      <th style="text-align: right">Polimorfizm çalışır mı?</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">Calisan c = y</code></td>
      <td style="text-align: right">Evet</td>
      <td style="text-align: right">Hayır</td>
      <td style="text-align: right">Hayır</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">Calisan&amp; c = y</code></td>
      <td style="text-align: right">Hayır</td>
      <td style="text-align: right">Evet</td>
      <td style="text-align: right">Evet</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">Calisan* c = &amp;y</code></td>
      <td style="text-align: right">Hayır</td>
      <td style="text-align: right">Evet</td>
      <td style="text-align: right">Evet</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">unique_ptr&lt;Calisan&gt;</code></td>
      <td style="text-align: right">Nesnenin kendisi kopyalanmaz</td>
      <td style="text-align: right">Evet</td>
      <td style="text-align: right">Evet</td>
    </tr>
  </tbody>
</table>

<p><img src="/img/c-nesne-dilimlenmesi-46.svg" alt="c-nesne-dilimlenmesi-46" /></p>

<h2 id="fonksiyon-parametrelerindeki-gizli-tuzak">Fonksiyon parametrelerindeki gizli tuzak</h2>

<p>Dilimlenme yalnızca açık atamalarda oluşmaz. Temel sınıfı değer olarak kabul eden fonksiyonlar da aynı soruna yol açar:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">bilgiYaz</span><span class="p">(</span><span class="n">Calisan</span> <span class="n">calisan</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// Değer ile alınıyor</span>
    <span class="n">calisan</span><span class="p">.</span><span class="n">tanit</span><span class="p">();</span>
<span class="p">}</span>

<span class="n">Yazilimci</span> <span class="n">y</span><span class="p">;</span>
<span class="n">bilgiYaz</span><span class="p">(</span><span class="n">y</span><span class="p">);</span> <span class="c1">// Parametre oluşturulurken dilimlenir</span>
</code></pre></div></div>

<p>Çözüm, parametreyi çoğunlukla sabit referansla almaktır:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">bilgiYaz</span><span class="p">(</span><span class="k">const</span> <span class="n">Calisan</span><span class="o">&amp;</span> <span class="n">calisan</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">calisan</span><span class="p">.</span><span class="n">tanit</span><span class="p">();</span> <span class="c1">// Gerçek türe göre çağrı yapılır</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Bu yöntem hem türetilmiş kimliği korur hem de gereksiz nesne kopyasını engeller. Fonksiyon nesneyi değiştirmeyecekse <code class="language-plaintext highlighter-rouge">const</code> kullanılması niyeti açıkça belirtir.</p>

<h2 id="koleksiyonlarda-doğru-tür-seçimi">Koleksiyonlarda doğru tür seçimi</h2>

<p><code class="language-plaintext highlighter-rouge">std::vector&lt;Calisan&gt;</code> içine <code class="language-plaintext highlighter-rouge">Yazilimci</code> eklemek de nesneyi dilimler. Farklı türetilmiş türleri aynı koleksiyonda polimorfik olarak saklamak için akıllı işaretçiler kullanılabilir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;memory&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;vector&gt;</span><span class="cp">
</span>
<span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">Calisan</span><span class="o">&gt;&gt;</span> <span class="n">ekip</span><span class="p">;</span>
<span class="n">ekip</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">make_unique</span><span class="o">&lt;</span><span class="n">Yazilimci</span><span class="o">&gt;</span><span class="p">());</span>

<span class="k">for</span> <span class="p">(</span><span class="k">const</span> <span class="k">auto</span><span class="o">&amp;</span> <span class="n">kisi</span> <span class="o">:</span> <span class="n">ekip</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">kisi</span><span class="o">-&gt;</span><span class="n">tanit</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Burada vektör nesnelerin kendilerini değil, temel sınıf türündeki sahiplik işaretçilerini saklar. Gerçek nesneler türetilmiş türleriyle yaşamaya devam eder. Temel sınıf üzerinden silme yapılacağı için yıkıcının da sanal olması gerekir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">virtual</span> <span class="o">~</span><span class="n">Calisan</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
</code></pre></div></div>

<p>Özetle, değer semantiği bilinçli bir temel sınıf kopyası istendiğinde uygundur; polimorfik davranış istendiğinde ise referanslar, işaretçiler ve akıllı işaretçiler tercih edilmelidir. Derleyicinin sessiz kalması işlemin zararsız olduğu anlamına gelmez: Nesnenin yalnızca üst dilimini servis edip geri kalanını mutfakta unutmuş olabilirsiniz.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="c++" /><category term="nesne yönelimli programlama" /><category term="object slicing" /><category term="kalıtım" /><category term="polimorfizm" /><category term="referanslar" /><summary type="html"><![CDATA[C++’ta kalıtım kullanırken türetilmiş bir nesneyi temel sınıf türündeki değişkene değer olarak atamak ilk bakışta zararsız görünebilir. Kod derlenir, program çalışır ve çoğu zaman hata mesajı da alınmaz. Fakat bu işlem sırasında nesnenin yalnızca temel sınıfa ait bölümü kopyalanır; türetilmiş sınıfın eklediği veriler ve davranış kimliği kaybolur. İşte bu sessiz bilgi kaybına nesne dilimlenmesi, yani object slicing denir.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/c-nesne-dilimlenmesi-46.png" /><media:content medium="image" url="https://program.sonsuz.us/img/c-nesne-dilimlenmesi-46.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">C++’ta Manuel Kaynak Yönetimi: Exception Gelince Sızıntı Başlar</title><link href="https://program.sonsuz.us/posts/cta-manuel-kaynak-yonetimi-exception-gelince-sizinti-baslar/" rel="alternate" type="text/html" title="C++’ta Manuel Kaynak Yönetimi: Exception Gelince Sızıntı Başlar" /><published>2026-10-23T00:00:00+00:00</published><updated>2026-10-23T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/cta-manuel-kaynak-yonetimi-exception-gelince-sizinti-baslar</id><content type="html" xml:base="https://program.sonsuz.us/posts/cta-manuel-kaynak-yonetimi-exception-gelince-sizinti-baslar/"><![CDATA[<p>C++ geliştirirken <code class="language-plaintext highlighter-rouge">new</code> ile bellek ayırıp işimiz bitince <code class="language-plaintext highlighter-rouge">delete</code> çağırmak ilk bakışta oldukça düzenli görünür. Fakat kodun ortasında bir istisna fırlatıldığında kontrol akışı planladığımız yolu izlemez. Temizlik satırına ulaşılamaz ve ayrılan kaynak sahipsiz kalır. Program çalışmaya devam etse bile bellekte küçük bir hayalet dolaşmaya başlar.</p>

<p>``</p>

<h2 id="sorun-yalnızca-delete-unutmak-değildir">Sorun yalnızca <code class="language-plaintext highlighter-rouge">delete</code> unutmak değildir</h2>

<p>Manuel kaynak yönetiminde genellikle kaynağın yaşam süresini zihnimizde takip ederiz: kaynağı edin, kullan ve serbest bırak. İdeal akış şöyle düşünülebilir:</p>

\[T_{yaşam} = T_{serbest\ bırakma} - T_{edinme}\]

<p>Ancak bir exception oluştuğunda fonksiyon normal dönüş noktasına ulaşmaz. C++ çalışma zamanı stack unwinding işlemini başlatır; yani çağrı yığınındaki yerel nesneler geriye doğru yok edilir. Ham işaretçinin kendisi yok olur fakat işaret ettiği dinamik nesne otomatik olarak silinmez.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;stdexcept&gt;</span><span class="cp">
</span>
<span class="kt">void</span> <span class="nf">veriyiIsle</span><span class="p">()</span> <span class="p">{</span>
    <span class="kt">int</span><span class="o">*</span> <span class="n">sayilar</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">int</span><span class="p">[</span><span class="mi">1000</span><span class="p">];</span>

    <span class="n">sayilar</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">42</span><span class="p">;</span>
    <span class="k">throw</span> <span class="n">std</span><span class="o">::</span><span class="n">runtime_error</span><span class="p">(</span><span class="s">"Dosya okunamadı"</span><span class="p">);</span>

    <span class="k">delete</span><span class="p">[]</span> <span class="n">sayilar</span><span class="p">;</span> <span class="c1">// Bu satıra hiçbir zaman ulaşılamaz.</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Buradaki sızıntının matematiksel özeti basittir:</p>

\[Ayrılan\ Kaynaklar - Serbest\ Bırakılan\ Kaynaklar &gt; 0\]

<p>Fonksiyon her çağrıldığında yeni bir blok ayrılır. Hata tekrarlanırsa kayıp miktarı birikir. Tek çağrıdaki sızıntı $M$ bayt ve hatalı çağrı sayısı $n$ ise toplam kayıp yaklaşık $n \times M$ olur.</p>

<h2 id="try-catch-ile-temizlik-yeterli-mi"><code class="language-plaintext highlighter-rouge">try-catch</code> ile temizlik yeterli mi?</h2>

<p>Kaynağı <code class="language-plaintext highlighter-rouge">catch</code> bloğunda temizlemek mümkündür, fakat çözüm hızla kırılganlaşır:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">veriyiIsle</span><span class="p">()</span> <span class="p">{</span>
    <span class="kt">int</span><span class="o">*</span> <span class="n">sayilar</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">int</span><span class="p">[</span><span class="mi">1000</span><span class="p">];</span>

    <span class="k">try</span> <span class="p">{</span>
        <span class="n">riskliIslem</span><span class="p">(</span><span class="n">sayilar</span><span class="p">);</span>
    <span class="p">}</span> <span class="k">catch</span> <span class="p">(...)</span> <span class="p">{</span>
        <span class="k">delete</span><span class="p">[]</span> <span class="n">sayilar</span><span class="p">;</span>
        <span class="k">throw</span><span class="p">;</span> <span class="c1">// Orijinal exception yeniden gönderilir.</span>
    <span class="p">}</span>

    <span class="k">delete</span><span class="p">[]</span> <span class="n">sayilar</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Bu kod sızıntıyı önleyebilir; ancak hem normal hem de hatalı yol için aynı temizlik işlemi yazılmıştır. Fonksiyona dosya tanıtıcısı, kilit veya ikinci bir bellek bloğu eklendiğinde olası çıkış yolları çoğalır. Ayrıca yanlış sırada temizlik yapmak ya da bir kaynağı iki kez serbest bırakmak mümkündür.</p>

<table>
  <thead>
    <tr>
      <th>Yaklaşım</th>
      <th style="text-align: right">Exception güvenliği</th>
      <th style="text-align: right">Bakım maliyeti</th>
      <th>Risk</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Ham işaretçi ve manuel <code class="language-plaintext highlighter-rouge">delete</code></td>
      <td style="text-align: right">Düşük</td>
      <td style="text-align: right">Yüksek</td>
      <td>Sızıntı, çift silme</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">try-catch</code> ile manuel temizlik</td>
      <td style="text-align: right">Orta</td>
      <td style="text-align: right">Yüksek</td>
      <td>Tekrarlı ve kırılgan kod</td>
    </tr>
    <tr>
      <td>RAII nesnesi</td>
      <td style="text-align: right">Yüksek</td>
      <td style="text-align: right">Düşük</td>
      <td>Sahiplik daha nettir</td>
    </tr>
    <tr>
      <td>Akıllı işaretçi</td>
      <td style="text-align: right">Yüksek</td>
      <td style="text-align: right">Düşük</td>
      <td>Yanlış işaretçi türü seçimi</td>
    </tr>
  </tbody>
</table>

<p><img src="/img/cta-manuel-kaynak-67.svg" alt="cta-manuel-kaynak-67" /></p>

<h2 id="güvenli-çözüm-raii">Güvenli çözüm: RAII</h2>

<p>RAII, kaynağın yaşam süresini bir nesnenin yaşam süresine bağlar. Kullanıcı manuel olarak yıkıcı çağırmaz; kapsam sona erdiğinde yıkıcı dil tarafından otomatik çağrılır. Exception oluşması da bu davranışı bozmaz.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;memory&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;stdexcept&gt;</span><span class="cp">
</span>
<span class="kt">void</span> <span class="nf">veriyiIsle</span><span class="p">()</span> <span class="p">{</span>
    <span class="k">auto</span> <span class="n">sayilar</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">make_unique</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">[]</span><span class="o">&gt;</span><span class="p">(</span><span class="mi">1000</span><span class="p">);</span>
    <span class="n">sayilar</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">42</span><span class="p">;</span>

    <span class="k">throw</span> <span class="n">std</span><span class="o">::</span><span class="n">runtime_error</span><span class="p">(</span><span class="s">"İşlem başarısız"</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">std::unique_ptr</code>, dizinin tek sahibidir. Stack unwinding sırasında <code class="language-plaintext highlighter-rouge">sayilar</code> nesnesinin yıkıcısı çalışır ve dinamik dizi serbest bırakılır. Açık bir <code class="language-plaintext highlighter-rouge">delete[]</code> satırına ihtiyaç kalmaz.</p>

<p>Çoğu durumda dinamik dizi için daha doğal seçenek <code class="language-plaintext highlighter-rouge">std::vector</code> kullanmaktır:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;vector&gt;</span><span class="cp">
</span>
<span class="kt">void</span> <span class="nf">veriyiIsle</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">sayilar</span><span class="p">(</span><span class="mi">1000</span><span class="p">);</span>
    <span class="n">sayilar</span><span class="p">.</span><span class="n">at</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">=</span> <span class="mi">42</span><span class="p">;</span>
    <span class="n">riskliIslem</span><span class="p">(</span><span class="n">sayilar</span><span class="p">.</span><span class="n">data</span><span class="p">());</span>
<span class="p">}</span>
</code></pre></div></div>

<p>RAII yalnızca bellek için değildir. Dosyalar, mutex kilitleri, soketler ve veritabanı bağlantıları da aynı ilkeyle kapsüllenebilir. Temel kural şudur: Kaynağı edinen nesne, onu bırakmaktan da sorumlu olmalıdır. Böylece exception geldiğinde temizlik bir dilek değil, kapsam mekanizmasının garantisi olur.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="c++" /><category term="raii" /><category term="exception" /><category term="bellek yönetimi" /><category term="akıllı işaretçiler" /><summary type="html"><![CDATA[C++ geliştirirken new ile bellek ayırıp işimiz bitince delete çağırmak ilk bakışta oldukça düzenli görünür. Fakat kodun ortasında bir istisna fırlatıldığında kontrol akışı planladığımız yolu izlemez. Temizlik satırına ulaşılamaz ve ayrılan kaynak sahipsiz kalır. Program çalışmaya devam etse bile bellekte küçük bir hayalet dolaşmaya başlar.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/cta-manuel-kaynak-67.png" /><media:content medium="image" url="https://program.sonsuz.us/img/cta-manuel-kaynak-67.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">MMORPG Sunucu Mimarisi: Binlerce Oyuncu Tek Dünyada Nasıl Buluşuyor?</title><link href="https://program.sonsuz.us/posts/mmorpg-sunucu-mimarisi-binlerce-oyuncu-tek-dunyada-nasil-bulusuyor/" rel="alternate" type="text/html" title="MMORPG Sunucu Mimarisi: Binlerce Oyuncu Tek Dünyada Nasıl Buluşuyor?" /><published>2026-10-23T00:00:00+00:00</published><updated>2026-10-23T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/mmorpg-sunucu-mimarisi-binlerce-oyuncu-tek-dunyada-nasil-bulusuyor</id><content type="html" xml:base="https://program.sonsuz.us/posts/mmorpg-sunucu-mimarisi-binlerce-oyuncu-tek-dunyada-nasil-bulusuyor/"><![CDATA[<p>Bir MMORPG dünyasına bağlanıp kalabalık bir şehre girdiğinizde yüzlerce oyuncuyu koşarken, ticaret yaparken ve devasa yaratıklarla savaşırken görebilirsiniz. Ekrandaki bu canlılığın arkasında ise tek bir süper bilgisayar değil; görevleri paylaşan, birbirleriyle sürekli haberleşen ve arızalara karşı hazırlıklı çalışan dağıtık sunucular bulunur.</p>

<p><img src="/img/mmorpg-sunucu-mimarisi-78.svg" alt="mmorpg-sunucu-mimarisi-78" /></p>

<p>``</p>
<h2 id="tek-sunucu-neden-yetmez">Tek Sunucu Neden Yetmez?</h2>

<p>Her oyuncu hareket, yetenek kullanımı, envanter yönetimi ve sohbet gibi olaylar üretir. Oyuncu başına saniyede ortalama $r$ mesaj, eşzamanlı oyuncu sayısı da $N$ ise sistemin karşılaması gereken yaklaşık mesaj yükü şöyledir:</p>

\[M = N \times r\]

<p>Örneğin 10.000 oyuncunun saniyede 15 mesaj ürettiği bir dünyada sunucular saniyede yaklaşık 150.000 mesajı işlemelidir. Üstelik bazı hareketler çevredeki diğer oyunculara da gönderilir. Her veriyi herkese yayınlamak maliyeti hızla $O(N^2)$ seviyesine taşıyabileceğinden MMORPG mimarileri dünyayı mantıksal parçalara ayırır.</p>

<h2 id="sunucu-katmanları">Sunucu Katmanları</h2>

<p>Oyuncu genellikle doğrudan oyun dünyasının merkezine bağlanmaz. İstek, uzmanlaşmış servislerden oluşan bir yolculuk yapar.</p>

<table>
  <thead>
    <tr>
      <th>Bileşen</th>
      <th>Temel görev</th>
      <th>Örnek veri</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Gateway</td>
      <td>Bağlantıyı kabul eder ve yönlendirir</td>
      <td>Oturum, paket, IP</td>
    </tr>
    <tr>
      <td>Kimlik servisi</td>
      <td>Hesabı doğrular</td>
      <td>Token, karakter listesi</td>
    </tr>
    <tr>
      <td>World server</td>
      <td>Dünya kurallarını yönetir</td>
      <td>Saat, hava, global etkinlik</td>
    </tr>
    <tr>
      <td>Zone server</td>
      <td>Belirli bir bölgeyi simüle eder</td>
      <td>Oyuncu, NPC, savaş</td>
    </tr>
    <tr>
      <td>Veritabanı</td>
      <td>Kalıcı veriyi saklar</td>
      <td>Envanter, görev, ekonomi</td>
    </tr>
    <tr>
      <td>Chat servisi</td>
      <td>Mesajlaşmayı yönetir</td>
      <td>Kanal ve özel mesaj</td>
    </tr>
  </tbody>
</table>

<p>Bu ayrım sayesinde sohbet sistemindeki yoğunluk savaş hesaplamalarını durdurmaz. Ayrıca her servis bağımsız biçimde ölçeklenebilir.</p>

<h2 id="shard-zone-ve-instance-farkı">Shard, Zone ve Instance Farkı</h2>

<p><strong>Shard</strong>, aynı oyunun ayrı bir kopyasıdır; oyuncular bunu genellikle “sunucu seçimi” olarak görür. <strong>Zone</strong>, tek dünyanın coğrafi bölümlere ayrılmasıdır. <strong>Instance</strong> ise zindan gibi belirli bir grup için geçici oluşturulan özel alandır.</p>

<table>
  <thead>
    <tr>
      <th>Yöntem</th>
      <th>Avantaj</th>
      <th>Dezavantaj</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Shard</td>
      <td>Güçlü izolasyon</td>
      <td>Oyuncu topluluğunu böler</td>
    </tr>
    <tr>
      <td>Zone</td>
      <td>Kesintisiz dünya hissi</td>
      <td>Sınır geçişleri karmaşıktır</td>
    </tr>
    <tr>
      <td>Instance</td>
      <td>Talebe göre kolay ölçeklenir</td>
      <td>Ortak dünya hissini azaltabilir</td>
    </tr>
  </tbody>
</table>

<p>Bir karakter bölge sınırını geçtiğinde eski zone sunucusu karakter durumunu yeni sunucuya aktarır. Bu <strong>handoff</strong> işlemi sırasında iki sunucunun kısa süreli koordinasyon kurması gerekir; aksi hâlde karakter kopyalanabilir veya kaybolabilir.</p>

<h2 id="interest-management-herkesi-herkese-gösterme">Interest Management: Herkesi Herkese Gösterme</h2>

<p>Bir oyuncunun kıtanın diğer ucundaki hareketleri bilmesine gerek yoktur. Sunucu, dünyayı hücrelere böler ve yalnızca görüş alanındaki nesneleri gönderir. Görüş yarıçapı $d$ olan bir oyuncu için ilgi alanı kabaca $A = \pi d^2$ olur.</p>

<p>Basitleştirilmiş bir yayın mantığı şöyle yazılabilir:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">broadcast_movement</span><span class="p">(</span><span class="n">player</span><span class="p">,</span> <span class="n">spatial_grid</span><span class="p">):</span>
    <span class="n">nearby</span> <span class="o">=</span> <span class="n">spatial_grid</span><span class="p">.</span><span class="nf">query</span><span class="p">(</span><span class="n">player</span><span class="p">.</span><span class="n">position</span><span class="p">,</span> <span class="n">radius</span><span class="o">=</span><span class="mi">80</span><span class="p">)</span>

    <span class="k">for</span> <span class="n">entity</span> <span class="ow">in</span> <span class="n">nearby</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">entity</span><span class="p">.</span><span class="nb">id</span> <span class="o">!=</span> <span class="n">player</span><span class="p">.</span><span class="nb">id</span><span class="p">:</span>
            <span class="n">entity</span><span class="p">.</span><span class="n">connection</span><span class="p">.</span><span class="nf">send</span><span class="p">({</span>
                <span class="sh">"</span><span class="s">type</span><span class="sh">"</span><span class="p">:</span> <span class="sh">"</span><span class="s">movement</span><span class="sh">"</span><span class="p">,</span>
                <span class="sh">"</span><span class="s">player_id</span><span class="sh">"</span><span class="p">:</span> <span class="n">player</span><span class="p">.</span><span class="nb">id</span><span class="p">,</span>
                <span class="sh">"</span><span class="s">position</span><span class="sh">"</span><span class="p">:</span> <span class="n">player</span><span class="p">.</span><span class="n">position</span>
            <span class="p">})</span>
</code></pre></div></div>

<p>Bu kod, hareket paketini yalnızca yakındaki varlıklara göndererek bant genişliği ve işlemci tüketimini azaltır. Gerçek sistemlerde grid, quadtree veya spatial hashing kullanılabilir.</p>

<h2 id="sunucu-otoritesi-ve-tutarlılık">Sunucu Otoritesi ve Tutarlılık</h2>

<p>İstemciye tamamen güvenilirse oyuncu “Ben ışınlandım ve boss’u tek vuruşta yendim” diyebilir. Bu nedenle çoğu MMORPG <strong>server-authoritative</strong> çalışır: İstemci niyeti bildirir, sonucu sunucu hesaplar. İstemci gecikmeyi gizlemek için tahmin yapabilir; ancak son söz sunucudadır.</p>

<p>Tüm veriler aynı tutarlılık seviyesine ihtiyaç duymaz. Hasar ve eşya transferi güçlü tutarlılık isterken oyuncunun birkaç santimetrelik konumu eventual consistency ile yönetilebilir. Kritik ekonomi işlemlerinde idempotency anahtarları ve veritabanı transaction’ları, aynı satın alma paketinin iki kez işlenmesini önler.</p>

<h2 id="gecikme-tick-ve-dayanıklılık">Gecikme, Tick ve Dayanıklılık</h2>

<p>Zone sunucuları dünyayı belirli aralıklarla günceller. Tick hızı $f$ ise bir tick süresi yaklaşık $T = 1/f$ saniyedir. 20 Hz çalışan bir sistem dünyayı her 50 milisaniyede bir hesaplar.</p>

<p>Sunucu çökmesine karşı karakter durumu periyodik kaydedilir; kritik olaylar mesaj kuyruğuna veya event log’a yazılır. Load balancer yeni bağlantıları sağlıklı sunuculara gönderirken izleme araçları CPU, gecikme ve paket kaybını takip eder. Sonuçta kesintisiz görünen fantastik dünya; bölümlendirme, ilgi alanı filtreleme, otoriter simülasyon ve dikkatli veri yönetiminin birlikte yaptığı oldukça gerçek bir mühendislik büyüsüdür.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="mmorpg" /><category term="sunucu-mimarisi" /><category term="dağıtık-sistemler" /><category term="oyun-programlama" /><category term="ağ-programlama" /><category term="ölçeklenebilirlik" /><summary type="html"><![CDATA[Bir MMORPG dünyasına bağlanıp kalabalık bir şehre girdiğinizde yüzlerce oyuncuyu koşarken, ticaret yaparken ve devasa yaratıklarla savaşırken görebilirsiniz. Ekrandaki bu canlılığın arkasında ise tek bir süper bilgisayar değil; görevleri paylaşan, birbirleriyle sürekli haberleşen ve arızalara karşı hazırlıklı çalışan dağıtık sunucular bulunur.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/mmorpg-sunucu-mimarisi-78.png" /><media:content medium="image" url="https://program.sonsuz.us/img/mmorpg-sunucu-mimarisi-78.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Order Book Algoritmaları: Alış ve Satış Emirlerinden Piyasanın Yapısını Okumak</title><link href="https://program.sonsuz.us/posts/order-book-algoritmalari-alis-ve-satis-emirlerinden-piyasanin-yapisini-okumak/" rel="alternate" type="text/html" title="Order Book Algoritmaları: Alış ve Satış Emirlerinden Piyasanın Yapısını Okumak" /><published>2026-10-23T00:00:00+00:00</published><updated>2026-10-23T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/order-book-algoritmalari-alis-ve-satis-emirlerinden-piyasanin-yapisini-okumak</id><content type="html" xml:base="https://program.sonsuz.us/posts/order-book-algoritmalari-alis-ve-satis-emirlerinden-piyasanin-yapisini-okumak/"><![CDATA[<p><img src="/img/order-book-algoritmalari-36.svg" alt="order-book-algoritmalari-36" /></p>

<p>Bir finansal piyasayı yalnızca son işlem fiyatından izlemek, futbol maçını sadece skor tabelasından takip etmeye benzer. Order book, yani emir defteri ise sahanın tamamını gösterir: Hangi fiyatlarda alıcılar bekliyor, satıcılar nerede yoğunlaşıyor ve likidite hangi tarafta inceliyor? Doğru algoritmalarla bu hareketli tabloyu inceleyerek piyasanın kısa vadeli yapısı hakkında değerli ipuçları çıkarabiliriz.</p>

<p>``</p>

<h2 id="emir-defterinin-temel-mantığı">Emir defterinin temel mantığı</h2>

<p>Emir defteri, gerçekleşmeyi bekleyen limit alış ve satış emirlerinin fiyat seviyelerine göre sıralanmış hâlidir. En yüksek alış fiyatına <strong>best bid</strong>, en düşük satış fiyatına ise <strong>best ask</strong> denir. Bu iki fiyat arasındaki fark spread olarak tanımlanır:</p>

\[S = P_{ask} - P_{bid}\]

<p>Spread küçüldükçe piyasanın genellikle daha likit olduğu düşünülür. Ancak tek başına spread yeterli değildir. En iyi fiyat seviyesinde yalnızca birkaç birim emir varsa büyük bir piyasa emri fiyatı hızla kaydırabilir.</p>

<p>Çoğu borsada eşleştirme motoru <strong>fiyat-zaman önceliği</strong> kullanır. Daha iyi fiyat önceliklidir; aynı fiyattaki emirler arasında önce giren emir önce gerçekleşir. Piyasa emirleri ise beklemez, defterdeki uygun limit emirlerini tüketir.</p>

<table>
  <thead>
    <tr>
      <th>Gösterge</th>
      <th>Ne anlatır?</th>
      <th>Olası yorum</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Dar spread</td>
      <td>Alış ve satış fiyatları yakın</td>
      <td>Yüksek likidite</td>
    </tr>
    <tr>
      <td>Derin bid tarafı</td>
      <td>Alış emirleri yoğun</td>
      <td>Kısa vadeli destek ihtimali</td>
    </tr>
    <tr>
      <td>İnce ask tarafı</td>
      <td>Satış likiditesi düşük</td>
      <td>Yukarı hareket kolaylaşabilir</td>
    </tr>
    <tr>
      <td>Hızlı emir iptali</td>
      <td>Likidite kalıcı değil</td>
      <td>Manipülasyon riski olabilir</td>
    </tr>
  </tbody>
</table>

<h2 id="dengesizlik-ve-mikro-fiyat">Dengesizlik ve mikro fiyat</h2>

<p>Defter analizinin popüler ölçülerinden biri <strong>order book imbalance</strong> değeridir. En iyi seviyedeki alış miktarı $B$, satış miktarı $A$ olsun:</p>

\[I = \frac{B-A}{B+A}\]

<p>$I$ değeri $1$ seviyesine yaklaştığında alış tarafı, $-1$ seviyesine yaklaştığında satış tarafı daha ağırdır. Sıfıra yakın değerler dengeli bir görünüm sunar. Bununla birlikte büyük alış miktarı kesin yükseliş anlamına gelmez; emir gerçekleşmeden iptal edilebilir.</p>

<p>Bir başka ölçü olan mikro fiyat, orta noktayı mevcut miktarlarla ağırlıklandırır:</p>

\[P_{micro} = \frac{P_{ask}B + P_{bid}A}{A+B}\]

<p>Mikro fiyat orta fiyattan yukarıdaysa alış baskısının, aşağıdaysa satış baskısının daha güçlü olduğu düşünülebilir.</p>

<h2 id="python-ile-basit-analiz">Python ile basit analiz</h2>

<p>Aşağıdaki fonksiyon, en iyi alış ve satış seviyelerinden spread, orta fiyat, dengesizlik ve mikro fiyat hesaplar:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">book_metrics</span><span class="p">(</span><span class="n">bids</span><span class="p">,</span> <span class="n">asks</span><span class="p">):</span>
    <span class="c1"># Her eleman: (fiyat, miktar)
</span>    <span class="n">best_bid</span><span class="p">,</span> <span class="n">bid_qty</span> <span class="o">=</span> <span class="nf">max</span><span class="p">(</span><span class="n">bids</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
    <span class="n">best_ask</span><span class="p">,</span> <span class="n">ask_qty</span> <span class="o">=</span> <span class="nf">min</span><span class="p">(</span><span class="n">asks</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>

    <span class="n">spread</span> <span class="o">=</span> <span class="n">best_ask</span> <span class="o">-</span> <span class="n">best_bid</span>
    <span class="n">midpoint</span> <span class="o">=</span> <span class="p">(</span><span class="n">best_bid</span> <span class="o">+</span> <span class="n">best_ask</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span>
    <span class="n">total_qty</span> <span class="o">=</span> <span class="n">bid_qty</span> <span class="o">+</span> <span class="n">ask_qty</span>

    <span class="n">imbalance</span> <span class="o">=</span> <span class="p">(</span><span class="n">bid_qty</span> <span class="o">-</span> <span class="n">ask_qty</span><span class="p">)</span> <span class="o">/</span> <span class="n">total_qty</span>
    <span class="n">microprice</span> <span class="o">=</span> <span class="p">(</span>
        <span class="n">best_ask</span> <span class="o">*</span> <span class="n">bid_qty</span> <span class="o">+</span> <span class="n">best_bid</span> <span class="o">*</span> <span class="n">ask_qty</span>
    <span class="p">)</span> <span class="o">/</span> <span class="n">total_qty</span>

    <span class="k">return</span> <span class="p">{</span>
        <span class="sh">'</span><span class="s">spread</span><span class="sh">'</span><span class="p">:</span> <span class="n">spread</span><span class="p">,</span>
        <span class="sh">'</span><span class="s">midpoint</span><span class="sh">'</span><span class="p">:</span> <span class="n">midpoint</span><span class="p">,</span>
        <span class="sh">'</span><span class="s">imbalance</span><span class="sh">'</span><span class="p">:</span> <span class="n">imbalance</span><span class="p">,</span>
        <span class="sh">'</span><span class="s">microprice</span><span class="sh">'</span><span class="p">:</span> <span class="n">microprice</span>
    <span class="p">}</span>

<span class="n">bids</span> <span class="o">=</span> <span class="p">[(</span><span class="mf">99.90</span><span class="p">,</span> <span class="mi">12</span><span class="p">),</span> <span class="p">(</span><span class="mf">99.80</span><span class="p">,</span> <span class="mi">25</span><span class="p">)]</span>
<span class="n">asks</span> <span class="o">=</span> <span class="p">[(</span><span class="mf">100.00</span><span class="p">,</span> <span class="mi">5</span><span class="p">),</span> <span class="p">(</span><span class="mf">100.10</span><span class="p">,</span> <span class="mi">18</span><span class="p">)]</span>
<span class="nf">print</span><span class="p">(</span><span class="nf">book_metrics</span><span class="p">(</span><span class="n">bids</span><span class="p">,</span> <span class="n">asks</span><span class="p">))</span>
</code></pre></div></div>

<p>Bu örnek yalnızca ilk seviyeyi inceler. Gerçek sistemlerde ilk 5, 10 veya 20 fiyat seviyesi ağırlıklı olarak değerlendirilir. Yakın seviyelere daha fazla önem vermek için $w_i=e^{-\lambda i}$ gibi azalan bir ağırlık kullanılabilir.</p>

<h2 id="gürültü-spoofing-ve-doğru-yorum">Gürültü, spoofing ve doğru yorum</h2>

<p>Order book bir niyet tablosudur; gerçekleşmiş işlemlerin kaydı değildir. Büyük bir emir güçlü destek gibi görünürken aniden iptal edilebilir. <strong>Spoofing</strong>, yatırımcıları yanıltmak amacıyla büyük emir gösterip bunları gerçekleşmeden kaldırma davranışıdır. Bu nedenle algoritma; emir ekleme, iptal ve gerçekleşme hızlarını birlikte izlemelidir.</p>

<p>Sağlam bir yaklaşım, order book verisini işlem hacmi, order flow imbalance ve fiyat değişimiyle birleştirir. Ayrıca sonuçlar farklı piyasa koşullarında geriye dönük test edilmelidir. Emir defteri geleceği söyleyen kristal küre değildir; fakat doğru ölçümlerle piyasanın kısa vadeli baskısını gösteren oldukça hassas bir radar olabilir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="order book" /><category term="algoritmik işlem" /><category term="piyasa mikro yapısı" /><category term="python" /><category term="finans" /><category term="veri analizi" /><summary type="html"><![CDATA[Bir finansal piyasayı yalnızca son işlem fiyatından izlemek, futbol maçını sadece skor tabelasından takip etmeye benzer. Order book, yani emir defteri ise sahanın tamamını gösterir: Hangi fiyatlarda alıcılar bekliyor, satıcılar nerede yoğunlaşıyor ve likidite hangi tarafta inceliyor? Doğru algoritmalarla bu hareketli tabloyu inceleyerek piyasanın kısa vadeli yapısı hakkında değerli ipuçları çıkarabiliriz.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/order-book-algoritmalari-36.png" /><media:content medium="image" url="https://program.sonsuz.us/img/order-book-algoritmalari-36.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Roguelike Türünün Felsefesi: Kalıcı Ölüm, Risk ve Öğrenme</title><link href="https://program.sonsuz.us/posts/roguelike-turunun-felsefesi-kalici-olum-risk-ve-ogrenme/" rel="alternate" type="text/html" title="Roguelike Türünün Felsefesi: Kalıcı Ölüm, Risk ve Öğrenme" /><published>2026-10-23T00:00:00+00:00</published><updated>2026-10-23T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/roguelike-turunun-felsefesi-kalici-olum-risk-ve-ogrenme</id><content type="html" xml:base="https://program.sonsuz.us/posts/roguelike-turunun-felsefesi-kalici-olum-risk-ve-ogrenme/"><![CDATA[<p><img src="/img/roguelike-turunun-felsefesi-61.svg" alt="roguelike-turunun-felsefesi-61" /></p>

<p>Roguelike oyunlarda ölüm, kısa bir yükleme ekranından çok daha fazlasıdır. Saatlerdir geliştirdiğiniz karakterin, topladığınız eşyaların ve kurduğunuz planların tek bir hatayla silinmesi mümkündür. <strong>Kalıcı ölüm</strong> olarak bilinen bu mekanik, oyuncuya yalnızca kaybetme korkusu yaşatmaz; karar verme, öğrenme ve risk değerlendirme biçimini de kökten değiştirir.
``</p>

<h2 id="ölüm-neden-bu-kadar-önemlidir">Ölüm neden bu kadar önemlidir?</h2>

<p>Geleneksel oyunlarda ölüm çoğunlukla geçici bir aksaklıktır. Oyuncu kayıt noktasına döner ve aynı bölümü küçük değişikliklerle tekrarlar. Roguelike türünde ise ölüm, mevcut koşunun sonudur. Bu nedenle oyuncu yalnızca ekrandaki düşmanla değil, verdiği kararların geri döndürülemezliğiyle de mücadele eder.</p>

<table>
  <thead>
    <tr>
      <th>Geleneksel kayıt sistemi</th>
      <th>Kalıcı ölüm sistemi</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Hata kolayca geri alınabilir</td>
      <td>Hatanın maliyeti yüksektir</td>
    </tr>
    <tr>
      <td>Deneme cesaretlendirilir</td>
      <td>Hazırlık ve gözlem öne çıkar</td>
    </tr>
    <tr>
      <td>Karakter ilerlemesi korunur</td>
      <td>Bilgi, ana ilerleme biçimine dönüşür</td>
    </tr>
    <tr>
      <td>Risk kısa vadeli düşünülür</td>
      <td>Risk koşunun bütünüyle değerlendirilir</td>
    </tr>
  </tbody>
</table>

<p>Bu fark, roguelike felsefesinin merkezindeki fikri ortaya çıkarır: <strong>Oyuncu karakteri kaybedebilir, fakat öğrendiklerini kaybetmez.</strong> Bir canavarın saldırı düzenini, zehrin etkisini veya hangi eşyanın hangi durumda değerli olduğunu öğrenmek, görünmeyen bir gelişim sistemidir.</p>

<h2 id="riskin-matematiği">Riskin matematiği</h2>

<p>Oyuncu bir odaya girmeden önce çoğu zaman sezgisel bir beklenen değer hesabı yapar. Bir kararın yaklaşık değeri şöyle gösterilebilir:</p>

\[E = P_b \times O - P_k \times M\]

<p>Burada $P_b$ başarı olasılığını, $O$ elde edilecek ödülü, $P_k$ kayıp olasılığını ve $M$ kaybın maliyetini temsil eder. Kalıcı ölümde $M$ çok büyüktür; çünkü yalnızca birkaç sağlık puanı değil, bütün koşu tehlikededir. Bu yüzden ödül yüksek olsa bile düşük başarı olasılığı oyuncuyu geri çekilmeye yöneltebilir.</p>

<p>Ancak insan zihni kusursuz bir hesap makinesi değildir. Nadir bir eşya görüldüğünde açgözlülük, uzun süren başarılı bir koşuda aşırı güven veya son anda gelen panik matematiksel değerlendirmeyi bozar. Roguelike oyunlar tam da bu duygusal çatışmadan beslenir: Mantık kapıyı kapatmayı söylerken merak içeride ne olduğunu fısıldar.</p>

<h2 id="basit-bir-risk-modeli">Basit bir risk modeli</h2>

<p>Bir oyunda karar puanlaması aşağıdaki gibi modellenebilir:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">risk_puani</span><span class="p">(</span><span class="n">odul</span><span class="p">,</span> <span class="n">basari_ihtimali</span><span class="p">,</span> <span class="n">kayip</span><span class="p">,</span> <span class="n">kaynak_orani</span><span class="p">):</span>
    <span class="n">beklenen_kazanc</span> <span class="o">=</span> <span class="n">odul</span> <span class="o">*</span> <span class="n">basari_ihtimali</span>
    <span class="n">beklenen_kayip</span> <span class="o">=</span> <span class="n">kayip</span> <span class="o">*</span> <span class="p">(</span><span class="mi">1</span> <span class="o">-</span> <span class="n">basari_ihtimali</span><span class="p">)</span>

    <span class="c1"># Kaynaklar azaldıkça aynı tehlike daha ciddi kabul edilir.
</span>    <span class="n">baski_carpani</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">+</span> <span class="p">(</span><span class="mi">1</span> <span class="o">-</span> <span class="n">kaynak_orani</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">beklenen_kazanc</span> <span class="o">-</span> <span class="n">beklenen_kayip</span> <span class="o">*</span> <span class="n">baski_carpani</span>
</code></pre></div></div>

<p>Bu kod, ödül ile olası kaybı karşılaştırır. <code class="language-plaintext highlighter-rouge">kaynak_orani</code>, oyuncunun sağlık, iksir veya mühimmat gibi kaynaklarının ne kadarının kaldığını belirtir. Sonuç negatifse çatışmadan kaçınmak mantıklı olabilir. Elbette iyi bir roguelike, bütün bilgileri açıkça sunmaz; belirsizlik, kararın heyecanını artırır.</p>

<h2 id="korkaklık-mı-ustalık-mı">Korkaklık mı, ustalık mı?</h2>

<p>Kalıcı ölüm başlangıçta oyuncuyu aşırı temkinli yapabilir. Her sandık tuzak, her koridor tehdit gibi görünür. Deneyim arttıkça temkin yerini <strong>hesaplanmış cesarete</strong> bırakır. Usta oyuncu hiçbir risk almayan kişi değildir; hangi riskin gerekli olduğunu anlayan kişidir.</p>

<p>Bu süreçte davranışlar belirgin biçimde değişir:</p>

<ul>
  <li>Kaynaklar hemen tüketilmek yerine kritik anlar için saklanır.</li>
  <li>Bilinmeyen düşmanlara doğrudan saldırmak yerine gözlem yapılır.</li>
  <li>Kaçış, başarısızlık değil stratejik bir araç olarak görülür.</li>
  <li>Kısa vadeli ödüller, uzun vadeli hayatta kalmayla karşılaştırılır.</li>
  <li>Her ölümden sonra neden-sonuç ilişkisi kurulmaya çalışılır.</li>
</ul>

<h2 id="yenilginin-anlamı">Yenilginin anlamı</h2>

<p>Roguelike türü, başarısızlığı oyunun karşıtı olmaktan çıkarıp oyunun parçasına dönüştürür. Adil tasarlanmış bir ölüm, oyuncuya cezadan çok ders verir: Yanlış eşya mı seçildi, gereksiz çatışmaya mı girildi, yoksa bilinmeyen bir mekanik mi gözden kaçtı?</p>

<p>Sonuç olarak kalıcı ölüm, yapay bir zorluk düğmesi değildir. Oyuncunun eşyalarla, zamanla ve kendi duygularıyla ilişkisini değiştiren felsefi bir tasarım tercihidir. Karakterler tekrar tekrar ölürken oyuncu giderek daha dikkatli, bilgili ve soğukkanlı hâle gelir. Roguelike deneyiminin gerçek kahramanı ekrandaki savaşçı değil, her yenilgiden sonra yeniden düşünen oyuncudur.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="roguelike" /><category term="oyun tasarımı" /><category term="kalıcı ölüm" /><category term="risk yönetimi" /><category term="oyuncu psikolojisi" /><summary type="html"><![CDATA[Roguelike oyunlarda ölüm, kısa bir yükleme ekranından çok daha fazlasıdır. Saatlerdir geliştirdiğiniz karakterin, topladığınız eşyaların ve kurduğunuz planların tek bir hatayla silinmesi mümkündür. Kalıcı ölüm olarak bilinen bu mekanik, oyuncuya yalnızca kaybetme korkusu yaşatmaz; karar verme, öğrenme ve risk değerlendirme biçimini de kökten değiştirir.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/roguelike-turunun-felsefesi-61.png" /><media:content medium="image" url="https://program.sonsuz.us/img/roguelike-turunun-felsefesi-61.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Bir Boşluk, Bütün Disk: rm -rf Komutunun Tehlikeli Anatomisi</title><link href="https://program.sonsuz.us/posts/bir-bosluk-butun-disk-rm-rf-komutunun-tehlikeli-anatomisi/" rel="alternate" type="text/html" title="Bir Boşluk, Bütün Disk: rm -rf Komutunun Tehlikeli Anatomisi" /><published>2026-10-22T00:00:00+00:00</published><updated>2026-10-22T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/bir-bosluk-butun-disk-rm-rf-komutunun-tehlikeli-anatomisi</id><content type="html" xml:base="https://program.sonsuz.us/posts/bir-bosluk-butun-disk-rm-rf-komutunun-tehlikeli-anatomisi/"><![CDATA[<p>Terminalde tek bir boşluğun ne kadar pahalı olabileceğini görmek istiyorsanız, <code class="language-plaintext highlighter-rouge">rm -rf</code> bunun en ürkütücü örneklerinden biridir. Yanlış yazılmış veya hatalı genişletilmiş bir yol; belgeleri, uygulamaları, yapılandırmaları ve yedekleri saniyeler içinde silebilir. Üstelik komut çoğunlukla “Emin misiniz?” diye sormaz. Klavyedeki minicik bir hata, dijital bir meteor etkisi oluşturabilir.</p>

<p>``</p>

<h2 id="rm--rf-gerçekte-ne-yapar"><code class="language-plaintext highlighter-rouge">rm -rf</code> gerçekte ne yapar?</h2>

<p><code class="language-plaintext highlighter-rouge">rm</code>, dosya ve dizinleri kaldırır. <code class="language-plaintext highlighter-rouge">-r</code> seçeneği dizinlerin içine özyinelemeli olarak girilmesini, <code class="language-plaintext highlighter-rouge">-f</code> ise uyarıların bastırılıp işlemin zorlanmasını sağlar. Başka bir deyişle komutun mantığı kabaca şöyledir:</p>

\[Silme\ Riski \approx Yetki \times Hedef\ Kapsamı \times Otomasyon\ Hızı\]

<p>Kök kullanıcı yetkisiyle geniş bir hedef seçildiğinde üç çarpan da büyür. Sonuç, geri dönüşüm kutusuna taşınan dosyalar değil; dosya sistemi kayıtlarının doğrudan kaldırılmasıdır.</p>

<table>
  <thead>
    <tr>
      <th>İfade</th>
      <th>Kabuğun yorumu</th>
      <th>Risk</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">rm -rf ./build</code></td>
      <td>Geçerli dizindeki <code class="language-plaintext highlighter-rouge">build</code> klasörü</td>
      <td>Sınırlı</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">rm -rf ./build/*</code></td>
      <td>Klasörün görünür içerikleri</td>
      <td>Orta</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">rm -rf /*</code></td>
      <td>Kök altındaki girdiler</td>
      <td>Felaket</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">rm -rf /</code></td>
      <td>Kök dizinin kendisi</td>
      <td>Felaket; bazı sistemlerde engellenir</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">rm -rf / tmp/proje</code></td>
      <td>İki ayrı hedef: <code class="language-plaintext highlighter-rouge">/</code> ve <code class="language-plaintext highlighter-rouge">tmp/proje</code></td>
      <td>Felaket</td>
    </tr>
  </tbody>
</table>

<p>Burada önemli bir düzeltme var: <code class="language-plaintext highlighter-rouge">rm -rf /</code> ile <code class="language-plaintext highlighter-rouge">rm -rf /*</code> arasındaki fark yalnızca boşluk değildir; yıldız karakteri kabuk tarafından genişletilir. Modern GNU <code class="language-plaintext highlighter-rouge">rm</code>, <code class="language-plaintext highlighter-rouge">/</code> hedefini genellikle <code class="language-plaintext highlighter-rouge">--preserve-root</code> korumasıyla reddeder. Ancak <code class="language-plaintext highlighter-rouge">/*</code>, kabuk tarafından <code class="language-plaintext highlighter-rouge">/etc</code>, <code class="language-plaintext highlighter-rouge">/home</code>, <code class="language-plaintext highlighter-rouge">/usr</code> gibi ayrı hedeflere dönüştürülebildiğinden bu korumayı aşabilir. Yani iki komut da güvenli değildir.</p>

<h2 id="boşluk-hatası-nasıl-felakete-dönüşür">Boşluk hatası nasıl felakete dönüşür?</h2>

<p>Shell, boşluğu argüman ayırıcı olarak kullanır. Örneğin amaç <code class="language-plaintext highlighter-rouge">/tmp/proje</code> içeriğini silmekken yanlışlıkla yolun ortasına boşluk eklenirse komut iki farklı hedef algılayabilir. Benzer şekilde boş bir değişken de beklenmeyen bir hedef meydana getirir:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># TEHLİKELİ ÖRNEK: Değişken boşsa hedef beklenenden farklılaşabilir.</span>
<span class="nb">rm</span> <span class="nt">-rf</span> <span class="s2">"</span><span class="nv">$TARGET</span><span class="s2">"</span>/<span class="k">*</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">TARGET</code> boş olduğunda ifade <code class="language-plaintext highlighter-rouge">/*</code> biçimine yaklaşır. Bu nedenle değişken kullanmadan önce hem doluluk hem de izin verilen kök yol denetlenmelidir.</p>

<h2 id="daha-güvenli-bir-silme-deseni">Daha güvenli bir silme deseni</h2>

<p>Aşağıdaki yaklaşım hedefi doğrular, mutlak yola dönüştürür ve yalnızca belirlenmiş çalışma alanı içindeki dizinlere izin verir:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/usr/bin/env bash</span>
<span class="nb">set</span> <span class="nt">-euo</span> pipefail

<span class="nv">target</span><span class="o">=</span><span class="s2">"</span><span class="k">${</span><span class="nv">1</span><span class="k">:-}</span><span class="s2">"</span>
<span class="nv">allowed_root</span><span class="o">=</span><span class="s2">"/srv/builds"</span>

<span class="k">if</span> <span class="o">[[</span> <span class="nt">-z</span> <span class="s2">"</span><span class="nv">$target</span><span class="s2">"</span> <span class="o">]]</span><span class="p">;</span> <span class="k">then
  </span><span class="nb">echo</span> <span class="s2">"Hata: Hedef boş olamaz."</span> <span class="o">&gt;</span>&amp;2
  <span class="nb">exit </span>1
<span class="k">fi

</span><span class="nv">resolved</span><span class="o">=</span><span class="s2">"</span><span class="si">$(</span><span class="nb">realpath</span> <span class="nt">--</span> <span class="s2">"</span><span class="nv">$target</span><span class="s2">"</span><span class="si">)</span><span class="s2">"</span>

<span class="k">if</span> <span class="o">[[</span> <span class="s2">"</span><span class="nv">$resolved</span><span class="s2">"</span> <span class="o">!=</span> <span class="s2">"</span><span class="nv">$allowed_root</span><span class="s2">"</span>/<span class="k">*</span> <span class="o">]]</span><span class="p">;</span> <span class="k">then
  </span><span class="nb">echo</span> <span class="s2">"Hata: İzin verilen alanın dışında: </span><span class="nv">$resolved</span><span class="s2">"</span> <span class="o">&gt;</span>&amp;2
  <span class="nb">exit </span>1
<span class="k">fi

</span><span class="nb">printf</span> <span class="s1">'Silinecek hedef: %s\n'</span> <span class="s2">"</span><span class="nv">$resolved</span><span class="s2">"</span>
<span class="nb">rm</span> <span class="nt">-rf</span> <span class="nt">--</span> <span class="s2">"</span><span class="nv">$resolved</span><span class="s2">"</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">set -u</code>, tanımsız değişkenleri hata kabul eder. <code class="language-plaintext highlighter-rouge">realpath</code>, <code class="language-plaintext highlighter-rouge">..</code> ve sembolik bağlantı kaynaklı belirsizlikleri azaltır. <code class="language-plaintext highlighter-rouge">--</code> ise tireyle başlayan bir dosya adının seçenek sanılmasını engeller. Yine de bu kod, yedeklemenin yerini tutmaz.</p>

<h2 id="kazayı-önlemek-için-pratik-kurallar">Kazayı önlemek için pratik kurallar</h2>

<ol>
  <li>Komutu çalıştırmadan önce hedefi <code class="language-plaintext highlighter-rouge">printf '%q\n' "$target"</code> ile görüntüleyin.</li>
  <li>Önce <code class="language-plaintext highlighter-rouge">ls</code> veya <code class="language-plaintext highlighter-rouge">find</code> kullanarak kapsamı inceleyin.</li>
  <li>Betiklerde <code class="language-plaintext highlighter-rouge">set -euo pipefail</code> etkinleştirin.</li>
  <li>Kritik işlemleri root yerine sınırlı yetkili kullanıcıyla yürütün.</li>
  <li>Snapshot ve çevrimdışı yedek bulundurun; aynı diskteki kopya gerçek yedek değildir.</li>
  <li>Etkileşimli kullanımda <code class="language-plaintext highlighter-rouge">rm -I</code> seçeneğini değerlendirin.</li>
</ol>

<p>Yanlış silme gerçekleşirse sistemi hemen kullanmayı bırakmak, diske yeni veri yazmamak ve profesyonel kurtarma araçlarına yönelmek gerekir. En iyi kurtarma stratejisi ise hâlâ kazadan önce hazırlanmış, düzenli olarak test edilen bir yedektir.</p>

<p><img src="/img/bir-bosluk-butun-16.svg" alt="bir-bosluk-butun-16" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="linux" /><category term="shell" /><category term="bash" /><category term="rm-komutu" /><category term="veri-güvenliği" /><category term="devops" /><summary type="html"><![CDATA[Terminalde tek bir boşluğun ne kadar pahalı olabileceğini görmek istiyorsanız, rm -rf bunun en ürkütücü örneklerinden biridir. Yanlış yazılmış veya hatalı genişletilmiş bir yol; belgeleri, uygulamaları, yapılandırmaları ve yedekleri saniyeler içinde silebilir. Üstelik komut çoğunlukla “Emin misiniz?” diye sormaz. Klavyedeki minicik bir hata, dijital bir meteor etkisi oluşturabilir.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/bir-bosluk-butun-16.png" /><media:content medium="image" url="https://program.sonsuz.us/img/bir-bosluk-butun-16.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">C++ Atama Operatöründe Copy-and-Swap ile Güçlü İstisna Güvenliği</title><link href="https://program.sonsuz.us/posts/c-atama-operatorunde-copy-and-swap-ile-guclu-istisna-guvenligi/" rel="alternate" type="text/html" title="C++ Atama Operatöründe Copy-and-Swap ile Güçlü İstisna Güvenliği" /><published>2026-10-22T00:00:00+00:00</published><updated>2026-10-22T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/c-atama-operatorunde-copy-and-swap-ile-guclu-istisna-guvenligi</id><content type="html" xml:base="https://program.sonsuz.us/posts/c-atama-operatorunde-copy-and-swap-ile-guclu-istisna-guvenligi/"><![CDATA[<p>C++’ta kaynak yöneten bir sınıfa atama operatörü yazmak, ilk bakışta birkaç alanı kopyalamaktan ibaret görünür. Fakat bellek ayırma işlemi yarıda başarısız olursa nesne hangi durumda kalacaktır? <strong>Copy-and-swap</strong>, yeni durumu önce güvenli bir geçici nesnede hazırlayıp yalnızca başarı kesinleştiğinde devreye alarak bu sorunu zarifçe çözer.</p>

<p><img src="/img/c-atama-operatorunde-36.svg" alt="c-atama-operatorunde-36" /></p>

<p>``</p>
<h2 id="önce-problem-sil-sonra-kopyala">Önce problem: Sil, sonra kopyala</h2>

<p>Dinamik dizi yöneten basit bir sınıf düşünelim. Tehlikeli bir atama operatörü eski belleği önce silebilir, ardından yeni bellek ayırmaya çalışabilir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Buffer</span><span class="o">&amp;</span> <span class="k">operator</span><span class="o">=</span><span class="p">(</span><span class="k">const</span> <span class="n">Buffer</span><span class="o">&amp;</span> <span class="n">other</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">delete</span><span class="p">[]</span> <span class="n">data_</span><span class="p">;</span>
    <span class="n">size_</span> <span class="o">=</span> <span class="n">other</span><span class="p">.</span><span class="n">size_</span><span class="p">;</span>
    <span class="n">data_</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">int</span><span class="p">[</span><span class="n">size_</span><span class="p">];</span> <span class="c1">// std::bad_alloc fırlatabilir</span>
    <span class="n">std</span><span class="o">::</span><span class="n">copy</span><span class="p">(</span><span class="n">other</span><span class="p">.</span><span class="n">data_</span><span class="p">,</span> <span class="n">other</span><span class="p">.</span><span class="n">data_</span> <span class="o">+</span> <span class="n">size_</span><span class="p">,</span> <span class="n">data_</span><span class="p">);</span>
    <span class="k">return</span> <span class="o">*</span><span class="k">this</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">new</code> başarısız olduğunda eski veri çoktan kaybedilmiştir. Üstelik <code class="language-plaintext highlighter-rouge">data_</code>, silinmiş belleği gösterebilir. Nesne artık yalnızca yanlış değil, yıkıcısı çalıştığında ikinci kez silme yapabilecek kadar tehlikelidir.</p>

<p>İstisna güvenliği genellikle üç seviyede değerlendirilir:</p>

<table>
  <thead>
    <tr>
      <th>Garanti</th>
      <th>İstisna sonrası durum</th>
      <th>Copy-and-swap</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Garanti yok</td>
      <td>Nesne bozulabilir</td>
      <td>Önler</td>
    </tr>
    <tr>
      <td>Temel garanti</td>
      <td>Nesne geçerlidir, değeri değişebilir</td>
      <td>Aşar</td>
    </tr>
    <tr>
      <td>Güçlü garanti</td>
      <td>İşlem ya tamamen olur ya hiç olmamış sayılır</td>
      <td>Sağlar</td>
    </tr>
    <tr>
      <td>Fırlatmama garantisi</td>
      <td>İşlem istisna üretmez</td>
      <td>Yalnızca <code class="language-plaintext highlighter-rouge">swap</code> için beklenir</td>
    </tr>
  </tbody>
</table>

<p>Güçlü garantiyi matematiksel olarak bir durum geçişi gibi ifade edebiliriz. Eski durum $S$, hedef durum $T$ ise:</p>

\[\operatorname{assign}(S,T)=
\begin{cases}
T, &amp; \text{işlem başarılıysa} \\
S, &amp; \text{istisna oluşursa}
\end{cases}\]

<p>Yani yarım kalmış, garip bir $S’$ durumuna izin verilmez.</p>

<h2 id="copy-and-swap-nasıl-çalışır">Copy-and-swap nasıl çalışır?</h2>

<p>Teknik üç adımdan oluşur:</p>

<ol>
  <li>Sağ taraftaki nesnenin geçici bir kopyasını oluştur.</li>
  <li>Geçici nesne ile mevcut nesnenin kaynaklarını değiştir.</li>
  <li>Geçici nesne kapsam dışına çıkınca eski kaynakları otomatik olarak yok etsin.</li>
</ol>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;algorithm&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;cstddef&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;utility&gt;</span><span class="cp">
</span>
<span class="k">class</span> <span class="nc">Buffer</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="k">explicit</span> <span class="n">Buffer</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">size</span> <span class="o">=</span> <span class="mi">0</span><span class="p">)</span>
        <span class="o">:</span> <span class="n">size_</span><span class="p">(</span><span class="n">size</span><span class="p">),</span> <span class="n">data_</span><span class="p">(</span><span class="n">size</span> <span class="o">?</span> <span class="k">new</span> <span class="kt">int</span><span class="p">[</span><span class="n">size</span><span class="p">]{}</span> <span class="o">:</span> <span class="nb">nullptr</span><span class="p">)</span> <span class="p">{}</span>

    <span class="n">Buffer</span><span class="p">(</span><span class="k">const</span> <span class="n">Buffer</span><span class="o">&amp;</span> <span class="n">other</span><span class="p">)</span>
        <span class="o">:</span> <span class="n">size_</span><span class="p">(</span><span class="n">other</span><span class="p">.</span><span class="n">size_</span><span class="p">),</span>
          <span class="n">data_</span><span class="p">(</span><span class="n">size_</span> <span class="o">?</span> <span class="k">new</span> <span class="kt">int</span><span class="p">[</span><span class="n">size_</span><span class="p">]</span> <span class="o">:</span> <span class="nb">nullptr</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">std</span><span class="o">::</span><span class="n">copy</span><span class="p">(</span><span class="n">other</span><span class="p">.</span><span class="n">data_</span><span class="p">,</span> <span class="n">other</span><span class="p">.</span><span class="n">data_</span> <span class="o">+</span> <span class="n">size_</span><span class="p">,</span> <span class="n">data_</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="n">Buffer</span><span class="p">(</span><span class="n">Buffer</span><span class="o">&amp;&amp;</span> <span class="n">other</span><span class="p">)</span> <span class="k">noexcept</span>
        <span class="o">:</span> <span class="n">size_</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">exchange</span><span class="p">(</span><span class="n">other</span><span class="p">.</span><span class="n">size_</span><span class="p">,</span> <span class="mi">0</span><span class="p">)),</span>
          <span class="n">data_</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">exchange</span><span class="p">(</span><span class="n">other</span><span class="p">.</span><span class="n">data_</span><span class="p">,</span> <span class="nb">nullptr</span><span class="p">))</span> <span class="p">{}</span>

    <span class="o">~</span><span class="n">Buffer</span><span class="p">()</span> <span class="p">{</span>
        <span class="k">delete</span><span class="p">[]</span> <span class="n">data_</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="k">friend</span> <span class="kt">void</span> <span class="n">swap</span><span class="p">(</span><span class="n">Buffer</span><span class="o">&amp;</span> <span class="n">a</span><span class="p">,</span> <span class="n">Buffer</span><span class="o">&amp;</span> <span class="n">b</span><span class="p">)</span> <span class="k">noexcept</span> <span class="p">{</span>
        <span class="k">using</span> <span class="n">std</span><span class="o">::</span><span class="n">swap</span><span class="p">;</span>
        <span class="n">swap</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">size_</span><span class="p">,</span> <span class="n">b</span><span class="p">.</span><span class="n">size_</span><span class="p">);</span>
        <span class="n">swap</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">data_</span><span class="p">,</span> <span class="n">b</span><span class="p">.</span><span class="n">data_</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="n">Buffer</span><span class="o">&amp;</span> <span class="k">operator</span><span class="o">=</span><span class="p">(</span><span class="n">Buffer</span> <span class="n">other</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">swap</span><span class="p">(</span><span class="o">*</span><span class="k">this</span><span class="p">,</span> <span class="n">other</span><span class="p">);</span>
        <span class="k">return</span> <span class="o">*</span><span class="k">this</span><span class="p">;</span>
    <span class="p">}</span>

<span class="k">private</span><span class="o">:</span>
    <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">size_</span><span class="p">{};</span>
    <span class="kt">int</span><span class="o">*</span> <span class="n">data_</span><span class="p">{};</span>
<span class="p">};</span>
</code></pre></div></div>

<p>Buradaki kritik ayrıntı, parametrenin <code class="language-plaintext highlighter-rouge">const Buffer&amp;</code> yerine <strong>değerle</strong> alınmasıdır. Bir lvalue gönderildiğinde kopya kurucu, rvalue gönderildiğinde ise taşıma kurucu geçici <code class="language-plaintext highlighter-rouge">other</code> nesnesini hazırlar. Böylece tek operatör hem kopyalama hem taşıma atamasını karşılayabilir.</p>

<p>Kopyalama sırasında <code class="language-plaintext highlighter-rouge">new</code> istisna fırlatırsa fonksiyon gövdesine henüz girilmez; <code class="language-plaintext highlighter-rouge">*this</code> değişmeden kalır. Kopya başarıyla oluşursa <code class="language-plaintext highlighter-rouge">swap</code> yalnızca boyut ve işaretçi gibi ucuz üyeleri değiştirir. Bu nedenle <code class="language-plaintext highlighter-rouge">swap</code> fonksiyonunun <code class="language-plaintext highlighter-rouge">noexcept</code> olması güçlü garantinin merkezidir. Değişimden sonra <code class="language-plaintext highlighter-rouge">other</code>, hedef nesnenin eski belleğini taşır ve yıkıcısı bu belleği temizler. RAII burada temizlik ekibidir; hem de fazla mesai ücreti istemez.</p>

<h2 id="geleneksel-atama-ile-karşılaştırma">Geleneksel atama ile karşılaştırma</h2>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Elle yazılmış atama</th>
      <th>Copy-and-swap</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Kendine atama kontrolü</td>
      <td>Genellikle <code class="language-plaintext highlighter-rouge">this != &amp;other</code> gerekir</td>
      <td>Doğal olarak güvenlidir</td>
    </tr>
    <tr>
      <td>Hata yönetimi</td>
      <td>Karmaşık geri alma kodu gerekir</td>
      <td>Geçici nesne geri almayı sağlar</td>
    </tr>
    <tr>
      <td>Kod tekrarı</td>
      <td>Yüksek olabilir</td>
      <td>Kopya kurucu ve <code class="language-plaintext highlighter-rouge">swap</code> yeniden kullanılır</td>
    </tr>
    <tr>
      <td>Performans</td>
      <td>Bellek yeniden kullanılabilir</td>
      <td>Her kopyada yeni kaynak ayırabilir</td>
    </tr>
  </tbody>
</table>

<p>Copy-and-swap temiz ve güvenlidir; ancak her zaman en hızlı çözüm değildir. Büyük tamponlarda mevcut kapasiteyi yeniden kullanmak önemliyse özel bir atama operatörü daha verimli olabilir. Ayrıca sınıf yalnızca <code class="language-plaintext highlighter-rouge">std::vector</code>, <code class="language-plaintext highlighter-rouge">std::string</code> ve akıllı işaretçiler gibi RAII türlerinden oluşuyorsa en iyi seçenek çoğu zaman <strong>Rule of Zero</strong>, yani özel atama operatörü yazmamaktır.</p>

<p>Özetle copy-and-swap, işlemi önce hazırla, sonra tek ve güvenli adımla yayımla yaklaşımıdır. <code class="language-plaintext highlighter-rouge">swap</code> gerçekten <code class="language-plaintext highlighter-rouge">noexcept</code> olduğu sürece atama işlemini bir veritabanı işlemi gibi davranmaya yaklaştırır: ya commit gerçekleşir ya da nesne eski hâlinde kalır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="c++" /><category term="copy-and-swap" /><category term="istisna-güvenliği" /><category term="operator-overloading" /><category term="raii" /><category term="modern-c++" /><summary type="html"><![CDATA[C++’ta kaynak yöneten bir sınıfa atama operatörü yazmak, ilk bakışta birkaç alanı kopyalamaktan ibaret görünür. Fakat bellek ayırma işlemi yarıda başarısız olursa nesne hangi durumda kalacaktır? Copy-and-swap, yeni durumu önce güvenli bir geçici nesnede hazırlayıp yalnızca başarı kesinleştiğinde devreye alarak bu sorunu zarifçe çözer.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/c-atama-operatorunde-36.png" /><media:content medium="image" url="https://program.sonsuz.us/img/c-atama-operatorunde-36.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">C# Diziler ve String İşlemleri: Veriyi Düzenlemenin Akıllı Yolları</title><link href="https://program.sonsuz.us/posts/c-diziler-ve-string-islemleri-veriyi-duzenlemenin-akilli-yollari/" rel="alternate" type="text/html" title="C# Diziler ve String İşlemleri: Veriyi Düzenlemenin Akıllı Yolları" /><published>2026-10-22T00:00:00+00:00</published><updated>2026-10-22T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/c-diziler-ve-string-islemleri-veriyi-duzenlemenin-akilli-yollari</id><content type="html" xml:base="https://program.sonsuz.us/posts/c-diziler-ve-string-islemleri-veriyi-duzenlemenin-akilli-yollari/"><![CDATA[<p>C# dünyasında diziler ve metinler, veriyi saklamanın ve işlemenin temel araçlarıdır. Bir sınıftaki notları, oyun haritasındaki hücreleri veya bir metindeki kelimeleri yönetirken bu yapılarla karşılaşırız. Diziler düzenli veri kutuları gibiyken <code class="language-plaintext highlighter-rouge">string</code>, karakterlerden oluşan özel ve değiştirilemez bir koleksiyondur. Gelin bu araçların teorisini ve pratik kullanımını birlikte inceleyelim.</p>

<p>``</p>

<h2 id="dizilerin-temel-mantığı">Dizilerin temel mantığı</h2>

<p>Dizi, aynı türden belirli sayıda elemanı ardışık indekslerle saklayan veri yapısıdır. İndeksler sıfırdan başladığı için uzunluğu $n$ olan bir dizinin geçerli indeks aralığı $0 \le i &lt; n$ şeklindedir. Bir elemana indeksle erişmenin zaman karmaşıklığı sabittir:</p>

\[T(n)=O(1)\]

<p>Buna karşılık aranan değerin konumu bilinmiyorsa tüm elemanların gezilmesi gerekebilir ve doğrusal aramanın maliyeti $O(n)$ olur.</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span><span class="p">[]</span> <span class="n">notlar</span> <span class="p">=</span> <span class="p">{</span> <span class="m">75</span><span class="p">,</span> <span class="m">90</span><span class="p">,</span> <span class="m">68</span><span class="p">,</span> <span class="m">100</span> <span class="p">};</span>
<span class="kt">int</span> <span class="n">toplam</span> <span class="p">=</span> <span class="m">0</span><span class="p">;</span>

<span class="k">foreach</span> <span class="p">(</span><span class="kt">int</span> <span class="n">not</span> <span class="k">in</span> <span class="n">notlar</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">toplam</span> <span class="p">+=</span> <span class="n">not</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">double</span> <span class="n">ortalama</span> <span class="p">=</span> <span class="p">(</span><span class="kt">double</span><span class="p">)</span><span class="n">toplam</span> <span class="p">/</span> <span class="n">notlar</span><span class="p">.</span><span class="n">Length</span><span class="p">;</span>
<span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">$"Ortalama: </span><span class="p">{</span><span class="n">ortalama</span><span class="p">:</span><span class="n">F2</span><span class="p">}</span><span class="s">"</span><span class="p">);</span>
</code></pre></div></div>

<p>Bu örnek tek boyutlu diziyi dolaşır. Tür dönüşümü yapılmasaydı iki <code class="language-plaintext highlighter-rouge">int</code> değerin bölümü tam sayı üretirdi; <code class="language-plaintext highlighter-rouge">(double)</code> dönüşümü küsuratı korur.</p>

<h2 id="çok-boyutlu-ve-düzensiz-diziler">Çok boyutlu ve düzensiz diziler</h2>

<p>Çok boyutlu diziler satır ve sütunları eşit olan dikdörtgen tabloları temsil eder. Düzensiz, yani jagged diziler ise her satırında farklı sayıda eleman taşıyabilen dizilerin dizisidir.</p>

<table>
  <thead>
    <tr>
      <th>Yapı</th>
      <th>Tanım</th>
      <th>Uygun kullanım</th>
      <th>Erişim biçimi</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Tek boyutlu</td>
      <td>Doğrusal eleman listesi</td>
      <td>Notlar, fiyatlar</td>
      <td><code class="language-plaintext highlighter-rouge">dizi[i]</code></td>
    </tr>
    <tr>
      <td>Çok boyutlu</td>
      <td>Dikdörtgen matris</td>
      <td>Tahta, tablo, piksel alanı</td>
      <td><code class="language-plaintext highlighter-rouge">dizi[i, j]</code></td>
    </tr>
    <tr>
      <td>Jagged</td>
      <td>Satır uzunlukları değişken yapı</td>
      <td>Gruplar, değişken seviyeler</td>
      <td><code class="language-plaintext highlighter-rouge">dizi[i][j]</code></td>
    </tr>
  </tbody>
</table>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span><span class="p">[,]</span> <span class="n">harita</span> <span class="p">=</span>
<span class="p">{</span>
    <span class="p">{</span> <span class="m">1</span><span class="p">,</span> <span class="m">0</span><span class="p">,</span> <span class="m">1</span> <span class="p">},</span>
    <span class="p">{</span> <span class="m">0</span><span class="p">,</span> <span class="m">1</span><span class="p">,</span> <span class="m">0</span> <span class="p">}</span>
<span class="p">};</span>

<span class="kt">int</span><span class="p">[][]</span> <span class="n">gruplar</span> <span class="p">=</span>
<span class="p">{</span>
    <span class="k">new</span><span class="p">[]</span> <span class="p">{</span> <span class="m">10</span><span class="p">,</span> <span class="m">20</span> <span class="p">},</span>
    <span class="k">new</span><span class="p">[]</span> <span class="p">{</span> <span class="m">30</span><span class="p">,</span> <span class="m">40</span><span class="p">,</span> <span class="m">50</span> <span class="p">},</span>
    <span class="k">new</span><span class="p">[]</span> <span class="p">{</span> <span class="m">60</span> <span class="p">}</span>
<span class="p">};</span>

<span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="n">harita</span><span class="p">[</span><span class="m">1</span><span class="p">,</span> <span class="m">1</span><span class="p">]);</span> <span class="c1">// 1</span>
<span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="n">gruplar</span><span class="p">[</span><span class="m">1</span><span class="p">][</span><span class="m">2</span><span class="p">]);</span> <span class="c1">// 50</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">int[,]</code> tek bir dikdörtgen bloktur. <code class="language-plaintext highlighter-rouge">int[][]</code> içindeki her satır ise bağımsız bir dizidir. Bu esneklik bellek kullanımını azaltabilir; ancak satırların ayrı ayrı oluşturulması ve kontrol edilmesi gerekir.</p>

<h2 id="string-karakter-dizisinden-daha-fazlası">String: Karakter dizisinden daha fazlası</h2>

<p><code class="language-plaintext highlighter-rouge">string</code>, kavramsal olarak karakter dizisine benzese de <strong>immutable</strong>, yani değiştirilemez bir referans türüdür. Birleştirme veya değiştirme işlemi mevcut metni düzenlemez; yeni bir <code class="language-plaintext highlighter-rouge">string</code> üretir.</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">string</span> <span class="n">mesaj</span> <span class="p">=</span> <span class="s">"  C# diziler eğlencelidir  "</span><span class="p">;</span>
<span class="kt">string</span> <span class="n">temiz</span> <span class="p">=</span> <span class="n">mesaj</span><span class="p">.</span><span class="nf">Trim</span><span class="p">();</span>
<span class="kt">string</span><span class="p">[]</span> <span class="n">kelimeler</span> <span class="p">=</span> <span class="n">temiz</span><span class="p">.</span><span class="nf">Split</span><span class="p">(</span><span class="sc">' '</span><span class="p">,</span> <span class="n">StringSplitOptions</span><span class="p">.</span><span class="n">RemoveEmptyEntries</span><span class="p">);</span>
<span class="kt">string</span> <span class="n">sonuc</span> <span class="p">=</span> <span class="kt">string</span><span class="p">.</span><span class="nf">Join</span><span class="p">(</span><span class="s">" | "</span><span class="p">,</span> <span class="n">kelimeler</span><span class="p">).</span><span class="nf">ToUpperInvariant</span><span class="p">();</span>

<span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="n">sonuc</span><span class="p">);</span>
</code></pre></div></div>

<p>Burada <code class="language-plaintext highlighter-rouge">Trim</code> kenar boşluklarını kaldırır, <code class="language-plaintext highlighter-rouge">Split</code> metni parçalara ayırır, <code class="language-plaintext highlighter-rouge">Join</code> parçaları yeniden birleştirir. <code class="language-plaintext highlighter-rouge">ToUpperInvariant</code>, sonucu kullanıcının bölgesel dil ayarlarından bağımsız biçimde büyük harfe dönüştürür.</p>

<table>
  <thead>
    <tr>
      <th>İşlem</th>
      <th>Yöntem</th>
      <th>Sonuç</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Arama</td>
      <td><code class="language-plaintext highlighter-rouge">Contains</code>, <code class="language-plaintext highlighter-rouge">IndexOf</code></td>
      <td>Metin veya konum bulur</td>
    </tr>
    <tr>
      <td>Parçalama</td>
      <td><code class="language-plaintext highlighter-rouge">Split</code>, <code class="language-plaintext highlighter-rouge">Substring</code></td>
      <td>Alt metin üretir</td>
    </tr>
    <tr>
      <td>Değiştirme</td>
      <td><code class="language-plaintext highlighter-rouge">Replace</code></td>
      <td>Yeni metin döndürür</td>
    </tr>
    <tr>
      <td>Doğrulama</td>
      <td><code class="language-plaintext highlighter-rouge">StartsWith</code>, <code class="language-plaintext highlighter-rouge">EndsWith</code></td>
      <td><code class="language-plaintext highlighter-rouge">bool</code> değer üretir</td>
    </tr>
  </tbody>
</table>

<h2 id="çok-sayıda-birleştirmede-stringbuilder">Çok sayıda birleştirmede StringBuilder</h2>

<p>Döngü içinde <code class="language-plaintext highlighter-rouge">+</code> kullanmak çok sayıda geçici nesne oluşturabilir. Bu durumda <code class="language-plaintext highlighter-rouge">StringBuilder</code>, değiştirilebilir bir karakter tamponu sunar:</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">using</span> <span class="nn">System.Text</span><span class="p">;</span>

<span class="kt">var</span> <span class="n">rapor</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">StringBuilder</span><span class="p">();</span>
<span class="k">foreach</span> <span class="p">(</span><span class="kt">int</span> <span class="n">not</span> <span class="k">in</span> <span class="n">notlar</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">rapor</span><span class="p">.</span><span class="nf">Append</span><span class="p">(</span><span class="s">"Not: "</span><span class="p">).</span><span class="nf">AppendLine</span><span class="p">(</span><span class="n">not</span><span class="p">.</span><span class="nf">ToString</span><span class="p">());</span>
<span class="p">}</span>

<span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="n">rapor</span><span class="p">.</span><span class="nf">ToString</span><span class="p">());</span>
</code></pre></div></div>

<p>Az sayıdaki birleştirmede string interpolation okunaklıdır; yoğun işlemlerde ise <code class="language-plaintext highlighter-rouge">StringBuilder</code> daha verimlidir. Özetle doğru dizi türünü veri şekline, doğru metin aracını da işlem yoğunluğuna göre seçmek hem performansı hem kod okunabilirliğini artırır.</p>

<p><img src="/img/c-diziler-ve-74.svg" alt="c-diziler-ve-74" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="csharp" /><category term="diziler" /><category term="string" /><category term="jagged-array" /><category term="stringbuilder" /><category term="programlama" /><summary type="html"><![CDATA[C# dünyasında diziler ve metinler, veriyi saklamanın ve işlemenin temel araçlarıdır. Bir sınıftaki notları, oyun haritasındaki hücreleri veya bir metindeki kelimeleri yönetirken bu yapılarla karşılaşırız. Diziler düzenli veri kutuları gibiyken string, karakterlerden oluşan özel ve değiştirilemez bir koleksiyondur. Gelin bu araçların teorisini ve pratik kullanımını birlikte inceleyelim.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/c-diziler-ve-74.png" /><media:content medium="image" url="https://program.sonsuz.us/img/c-diziler-ve-74.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">C++ Fonksiyonlarında Referans mı, İşaretçi mi? Semantik Belirsizlikleri Çözmek</title><link href="https://program.sonsuz.us/posts/c-fonksiyonlarinda-referans-mi-isaretci-mi-semantik-belirsizlikleri-cozmek/" rel="alternate" type="text/html" title="C++ Fonksiyonlarında Referans mı, İşaretçi mi? Semantik Belirsizlikleri Çözmek" /><published>2026-10-22T00:00:00+00:00</published><updated>2026-10-22T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/c-fonksiyonlarinda-referans-mi-isaretci-mi-semantik-belirsizlikleri-cozmek</id><content type="html" xml:base="https://program.sonsuz.us/posts/c-fonksiyonlarinda-referans-mi-isaretci-mi-semantik-belirsizlikleri-cozmek/"><![CDATA[<p>C++ geliştirirken <code class="language-plaintext highlighter-rouge">T&amp;</code> ile <code class="language-plaintext highlighter-rouge">T*</code> arasındaki fark yalnızca sözdiziminden ibaret değildir. Bu iki parametre biçimi; null olasılığı, sahiplik, yeniden bağlanma ve fonksiyonun çağıranın nesnesini değiştirip değiştirmediği hakkında farklı mesajlar verir. Yanlış seçim yapıldığında kod derlenebilir, hatta yıllarca çalışabilir; ancak API’nin niyeti sisli bir İstanbul sabahına döner.</p>

<p>``</p>

<h2 id="temel-zihinsel-model">Temel zihinsel model</h2>

<p>Referans, var olan bir nesne için alternatif bir ad gibi düşünülebilir. İşaretçi ise bir nesnenin adresini tutan ayrı bir değerdir. Bir nesnenin adresi $A$ ise işaretçi kabaca $p = A$ ilişkisini taşır; <code class="language-plaintext highlighter-rouge">*p</code> ifadesi de o adresteki nesneye erişir. Referansta ise <code class="language-plaintext highlighter-rouge">r</code>, doğrudan aynı nesneyi temsil eder:</p>

\[r \equiv x, \qquad p = \&amp;x\]

<p>Bu benzerlik, ikisinin aynı semantiğe sahip olduğu anlamına gelmez.</p>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Referans (<code class="language-plaintext highlighter-rouge">T&amp;</code>)</th>
      <th>İşaretçi (<code class="language-plaintext highlighter-rouge">T*</code>)</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Null olabilir mi?</td>
      <td>Dil seviyesinde hayır</td>
      <td>Evet</td>
    </tr>
    <tr>
      <td>Yeniden bağlanabilir mi?</td>
      <td>Hayır</td>
      <td>Evet</td>
    </tr>
    <tr>
      <td>Kullanım sözdizimi</td>
      <td><code class="language-plaintext highlighter-rouge">value.member</code></td>
      <td><code class="language-plaintext highlighter-rouge">value-&gt;member</code></td>
    </tr>
    <tr>
      <td>İsteğe bağlı parametre mesajı</td>
      <td>Uygun değil</td>
      <td>Uygun olabilir</td>
    </tr>
    <tr>
      <td>Sahiplik belirtir mi?</td>
      <td>Genellikle hayır</td>
      <td>Tek başına belirsiz</td>
    </tr>
  </tbody>
</table>

<p><img src="/img/c-fonksiyonlarinda-referans-98.svg" alt="c-fonksiyonlarinda-referans-98" /></p>

<h2 id="fonksiyon-parametrelerindeki-asıl-belirsizlik">Fonksiyon parametrelerindeki asıl belirsizlik</h2>

<p>Aşağıdaki iki fonksiyon teknik olarak aynı nesneyi değiştirebilir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">increase</span><span class="p">(</span><span class="kt">int</span><span class="o">&amp;</span> <span class="n">value</span><span class="p">)</span> <span class="p">{</span>
    <span class="o">++</span><span class="n">value</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">void</span> <span class="nf">increase</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">value</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">value</span> <span class="o">!=</span> <span class="nb">nullptr</span><span class="p">)</span> <span class="p">{</span>
        <span class="o">++</span><span class="p">(</span><span class="o">*</span><span class="n">value</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Çağrı biçimleri ise farklı niyetler taşır:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="n">score</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span>
<span class="n">increase</span><span class="p">(</span><span class="n">score</span><span class="p">);</span>   <span class="c1">// Değişiklik ihtimali çağrı noktasında az görünür.</span>
<span class="n">increase</span><span class="p">(</span><span class="o">&amp;</span><span class="n">score</span><span class="p">);</span>  <span class="c1">// Adres verilmesi değişiklik sinyalini güçlendirir.</span>
</code></pre></div></div>

<p>Referans kullanan ilk çağrı, değer ile aktarılıyormuş gibi görünebilir. Fonksiyon bildirimi görülmüyorsa okuyucu <code class="language-plaintext highlighter-rouge">score</code> değişecek mi diye duraksar. İşaretçili çağrı daha görünürdür; fakat bu kez başka sorular doğar: <code class="language-plaintext highlighter-rouge">nullptr</code> geçerli mi, fonksiyon belleği serbest bırakacak mı, adres daha sonra saklanacak mı?</p>

<p>Dolayısıyla belirsizlik sözdiziminden çok, belgelenmemiş sözleşmeden kaynaklanır.</p>

<h2 id="const-pusulasını-kullanmak"><code class="language-plaintext highlighter-rouge">const</code> pusulasını kullanmak</h2>

<p><code class="language-plaintext highlighter-rouge">const</code>, fonksiyonun niyetini belirginleştiren en önemli araçlardan biridir:</p>

<table>
  <thead>
    <tr>
      <th>Bildirim</th>
      <th>Verdiği mesaj</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">const T&amp; value</code></td>
      <td>Nesne zorunlu, kopyalanmayacak ve değiştirilmeyecek</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">T&amp; value</code></td>
      <td>Nesne zorunlu ve değiştirilebilir</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">const T* value</code></td>
      <td>Nesne isteğe bağlı olabilir, varsa değiştirilmeyecek</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">T* value</code></td>
      <td>Nesne isteğe bağlı olabilir ve değiştirilebilir</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">T*&amp; value</code></td>
      <td>İşaretçinin kendisi de değiştirilebilir</td>
    </tr>
  </tbody>
</table>

<p>Özellikle <code class="language-plaintext highlighter-rouge">T*&amp;</code> sık karıştırılır. Burada fonksiyon yalnızca nesneyi değil, çağıranın işaretçisini de başka bir adrese yöneltebilir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">selectDefault</span><span class="p">(</span><span class="n">User</span><span class="o">*&amp;</span> <span class="n">current</span><span class="p">,</span> <span class="n">User</span><span class="o">&amp;</span> <span class="n">fallback</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">current</span> <span class="o">==</span> <span class="nb">nullptr</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">current</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">fallback</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Bu davranış gerçekten gerekiyorsa bildirim anlamlıdır. Yalnızca nesneyi değiştirmek isteniyorsa <code class="language-plaintext highlighter-rouge">User*</code> veya <code class="language-plaintext highlighter-rouge">User&amp;</code> daha doğru olur.</p>

<h2 id="sahiplik-tuzağı">Sahiplik tuzağı</h2>

<p>Ham işaretçi sahipliği açıklamaz. <code class="language-plaintext highlighter-rouge">Widget*</code> gören kişi nesnenin kim tarafından yok edileceğini bilemez. Modern C++’ta sahiplik için akıllı işaretçiler tercih edilmelidir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">inspect</span><span class="p">(</span><span class="k">const</span> <span class="n">Widget</span><span class="o">&amp;</span> <span class="n">widget</span><span class="p">);</span>             <span class="c1">// Ödünç alır, null olamaz.</span>
<span class="kt">void</span> <span class="nf">inspect</span><span class="p">(</span><span class="k">const</span> <span class="n">Widget</span><span class="o">*</span> <span class="n">widget</span><span class="p">);</span>             <span class="c1">// Ödünç alır, null olabilir.</span>
<span class="kt">void</span> <span class="nf">consume</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">Widget</span><span class="o">&gt;</span> <span class="n">widget</span><span class="p">);</span>   <span class="c1">// Sahipliği devralır.</span>
<span class="kt">void</span> <span class="nf">share</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">shared_ptr</span><span class="o">&lt;</span><span class="n">Widget</span><span class="o">&gt;</span> <span class="n">widget</span><span class="p">);</span>      <span class="c1">// Ortak sahiplik kurar.</span>
</code></pre></div></div>

<p>Buradaki isimler ve türler birlikte okununca API’nin sözleşmesi büyük ölçüde anlaşılır.</p>

<h2 id="pratik-seçim-rehberi">Pratik seçim rehberi</h2>

<p>Parametre zorunluysa ve sahiplik aktarılmıyorsa referans kullanın. Yokluğu anlamlı bir durumsa işaretçi veya daha açık bir soyutlama seçin. Salt okuma için <code class="language-plaintext highlighter-rouge">const T&amp;</code>, küçük ve ucuz türler için değer aktarımı tercih edin. Sahiplik aktarımını ham işaretçiyle gizlemeyin; <code class="language-plaintext highlighter-rouge">std::unique_ptr</code> ya da <code class="language-plaintext highlighter-rouge">std::shared_ptr</code> ile görünür kılın.</p>

<p>Kısacası referans ve işaretçi birbirinin süslü yazılmış hâli değildir. İyi tasarlanmış bir fonksiyon imzası, yalnızca derleyiciye tür bilgisi vermez; okuyucuya null, değişiklik ve sahiplik hakkında küçük ama güvenilir bir hikâye anlatır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="c++" /><category term="referans" /><category term="işaretçi" /><category term="fonksiyonlar" /><category term="api-tasarımı" /><category term="bellek-yönetimi" /><summary type="html"><![CDATA[C++ geliştirirken T&amp; ile T* arasındaki fark yalnızca sözdiziminden ibaret değildir. Bu iki parametre biçimi; null olasılığı, sahiplik, yeniden bağlanma ve fonksiyonun çağıranın nesnesini değiştirip değiştirmediği hakkında farklı mesajlar verir. Yanlış seçim yapıldığında kod derlenebilir, hatta yıllarca çalışabilir; ancak API’nin niyeti sisli bir İstanbul sabahına döner.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/c-fonksiyonlarinda-referans-98.png" /><media:content medium="image" url="https://program.sonsuz.us/img/c-fonksiyonlarinda-referans-98.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">C++ İsim Alanları: Büyük Projelerde İsim Çakışmalarına Son</title><link href="https://program.sonsuz.us/posts/c-isim-alanlari-buyuk-projelerde-isim-cakismalarina-son/" rel="alternate" type="text/html" title="C++ İsim Alanları: Büyük Projelerde İsim Çakışmalarına Son" /><published>2026-10-22T00:00:00+00:00</published><updated>2026-10-22T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/c-isim-alanlari-buyuk-projelerde-isim-cakismalarina-son</id><content type="html" xml:base="https://program.sonsuz.us/posts/c-isim-alanlari-buyuk-projelerde-isim-cakismalarina-son/"><![CDATA[<p><img src="/img/c-isim-alanlari-19.svg" alt="c-isim-alanlari-19" /></p>

<p>Bir projede yalnızca birkaç değişken ve sınıf varken isim bulmak kolaydır. Ancak kod tabanı büyüdükçe farklı geliştiricilerin aynı <code class="language-plaintext highlighter-rouge">Logger</code>, <code class="language-plaintext highlighter-rouge">Config</code> veya <code class="language-plaintext highlighter-rouge">User</code> adını kullanması kaçınılmaz hâle gelir. C++ isim alanları, yani <code class="language-plaintext highlighter-rouge">namespace</code> yapıları, bu isimleri mantıksal gruplara ayırarak derleyiciye hangi varlığı kastettiğimizi söyler. Kısacası namespace, kod dünyasının mahalle adresidir: Aynı isimli iki kişi olabilir, yeter ki farklı adreslerde yaşasın!</p>

<p>``</p>

<h2 id="i̇sim-çakışması-neden-oluşur">İsim çakışması neden oluşur?</h2>

<p>C++ dilinde bir ismin hangi bölgeden erişilebilir olduğunu belirleyen kurallara <strong>kapsam</strong>, yani scope denir. Global kapsamda tanımlanan isimler projenin birçok noktasından görülebildiği için çakışma olasılığı yükselir. Bir projede birbirinden bağımsız $n$ bileşen ve her bileşende ortalama $k$ genel isim bulunduğunu düşünelim. Karşılaştırılabilecek isim çiftlerinin sayısı yaklaşık olarak şöyledir:</p>

\[P = \frac{(nk)(nk-1)}{2}\]

<p>Bu ifade doğrudan kesin çakışma sayısını vermez; proje büyüdükçe riskin neden hızla arttığını gösterir. İsimleri namespace gruplarına bölmek, karşılaştırma alanını küçültür.</p>

<table>
  <thead>
    <tr>
      <th>Yaklaşım</th>
      <th>Kullanım örneği</th>
      <th style="text-align: right">Çakışma riski</th>
      <th>Okunabilirlik</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Global isim</td>
      <td><code class="language-plaintext highlighter-rouge">Logger</code></td>
      <td style="text-align: right">Yüksek</td>
      <td>Orta</td>
    </tr>
    <tr>
      <td>Namespace içindeki isim</td>
      <td><code class="language-plaintext highlighter-rouge">app::Logger</code></td>
      <td style="text-align: right">Düşük</td>
      <td>Yüksek</td>
    </tr>
    <tr>
      <td>İç içe namespace</td>
      <td><code class="language-plaintext highlighter-rouge">company::app::Logger</code></td>
      <td style="text-align: right">Çok düşük</td>
      <td>Yüksek</td>
    </tr>
  </tbody>
</table>

<h2 id="temel-namespace-kullanımı">Temel namespace kullanımı</h2>

<p>Bir isim alanı <code class="language-plaintext highlighter-rouge">namespace</code> anahtar sözcüğüyle tanımlanır. Aynı sınıf adı farklı alanlarda güvenle bulunabilir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;string&gt;</span><span class="cp">
</span>
<span class="k">namespace</span> <span class="n">Database</span> <span class="p">{</span>
    <span class="k">class</span> <span class="nc">Connection</span> <span class="p">{</span>
    <span class="nl">public:</span>
        <span class="kt">void</span> <span class="n">open</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span>
            <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Veritabanı bağlantısı açıldı.</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
        <span class="p">}</span>
    <span class="p">};</span>
<span class="p">}</span>

<span class="k">namespace</span> <span class="n">Network</span> <span class="p">{</span>
    <span class="k">class</span> <span class="nc">Connection</span> <span class="p">{</span>
    <span class="nl">public:</span>
        <span class="kt">void</span> <span class="n">open</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span>
            <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Ağ bağlantısı açıldı.</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
        <span class="p">}</span>
    <span class="p">};</span>
<span class="p">}</span>

<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">Database</span><span class="o">::</span><span class="n">Connection</span> <span class="n">database</span><span class="p">;</span>
    <span class="n">Network</span><span class="o">::</span><span class="n">Connection</span> <span class="n">network</span><span class="p">;</span>

    <span class="n">database</span><span class="p">.</span><span class="n">open</span><span class="p">();</span>
    <span class="n">network</span><span class="p">.</span><span class="n">open</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Buradaki <code class="language-plaintext highlighter-rouge">::</code> operatörüne <strong>kapsam çözümleme operatörü</strong> denir. <code class="language-plaintext highlighter-rouge">Database::Connection</code>, derleyiciye yalnızca <code class="language-plaintext highlighter-rouge">Connection</code> sınıfını değil, sınıfın tam adresini verir.</p>

<h2 id="using-kullanırken-dikkat"><code class="language-plaintext highlighter-rouge">using</code> kullanırken dikkat</h2>

<p>Uzun isimleri sürekli yazmamak için <code class="language-plaintext highlighter-rouge">using</code> bildirimi kullanılabilir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">using</span> <span class="n">Database</span><span class="o">::</span><span class="n">Connection</span><span class="p">;</span>

<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">Connection</span> <span class="n">connection</span><span class="p">;</span>
    <span class="n">connection</span><span class="p">.</span><span class="n">open</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Bu yöntem yalnızca ihtiyaç duyulan ismi mevcut kapsama taşır. Buna karşılık aşağıdaki kullanım özellikle başlık dosyalarında risklidir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>
</code></pre></div></div>

<p>Bu ifade <code class="language-plaintext highlighter-rouge">std</code> içindeki çok sayıda ismi görünür yapar. Projede başka bir <code class="language-plaintext highlighter-rouge">count</code>, <code class="language-plaintext highlighter-rouge">distance</code> veya <code class="language-plaintext highlighter-rouge">begin</code> tanımı varsa belirsizlik oluşabilir.</p>

<table>
  <thead>
    <tr>
      <th>Yöntem</th>
      <th>Avantaj</th>
      <th>Dezavantaj</th>
      <th>Öneri</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">std::string</code></td>
      <td>Açık ve güvenli</td>
      <td>Biraz uzun</td>
      <td>Genel olarak tercih edilir</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">using std::string</code></td>
      <td>Kısa ve kontrollü</td>
      <td>Yerel çakışma olabilir</td>
      <td>Dar kapsamda kullanılabilir</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">using namespace std</code></td>
      <td>Çok kısa</td>
      <td>Pek çok ismi içeri taşır</td>
      <td>Başlık dosyalarında kaçınılmalıdır</td>
    </tr>
  </tbody>
</table>

<h2 id="i̇ç-içe-ve-anonim-namespace">İç içe ve anonim namespace</h2>

<p>Modern C++ ile iç içe isim alanları daha kısa yazılabilir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">namespace</span> <span class="n">company</span><span class="o">::</span><span class="n">project</span><span class="o">::</span><span class="n">logging</span> <span class="p">{</span>
    <span class="kt">void</span> <span class="n">write</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">message</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">message</span> <span class="o">&lt;&lt;</span> <span class="sc">'\n'</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Fonksiyonun tam adı <code class="language-plaintext highlighter-rouge">company::project::logging::write</code> olur. Bu yapı şirket, ürün ve modül katmanlarını ifade etmek için kullanışlıdır.</p>

<p>Anonim namespace ise bir kaynak dosyasındaki isimleri yalnızca o çeviri birimine özel tutar:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">namespace</span> <span class="p">{</span>
    <span class="kt">int</span> <span class="n">calculateSecretValue</span><span class="p">()</span> <span class="p">{</span>
        <span class="k">return</span> <span class="mi">42</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Bu fonksiyona başka bir <code class="language-plaintext highlighter-rouge">.cpp</code> dosyasından erişilemez. Böylece uygulama içi yardımcı fonksiyonlar dış dünyaya sızmaz.</p>

<h2 id="pratik-kurallar">Pratik kurallar</h2>

<ul>
  <li>Namespace adlarını modül sınırlarına göre seçin.</li>
  <li>Başlık dosyalarında <code class="language-plaintext highlighter-rouge">using namespace</code> kullanmayın.</li>
  <li>Çok genel <code class="language-plaintext highlighter-rouge">Utils</code> veya <code class="language-plaintext highlighter-rouge">Common</code> adları yerine anlamlı alanlar oluşturun.</li>
  <li>Genel API’lerde kısa ama ayırt edici isimler tercih edin.</li>
  <li>Aynı namespace’i birden fazla dosyada genişletebileceğinizi unutmayın.</li>
</ul>

<p>Doğru namespace tasarımı yalnızca derleyici hatalarını önlemez; kodun sahibini, amacını ve mimari konumunu da anlatır. Büyük bir C++ projesinde düzen, iyi seçilmiş isimlerle; güvenlik ise o isimlere doğru adresleri vermekle başlar.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="c++" /><category term="namespace" /><category term="isim alanları" /><category term="yazılım mimarisi" /><category term="modüler programlama" /><summary type="html"><![CDATA[Bir projede yalnızca birkaç değişken ve sınıf varken isim bulmak kolaydır. Ancak kod tabanı büyüdükçe farklı geliştiricilerin aynı Logger, Config veya User adını kullanması kaçınılmaz hâle gelir. C++ isim alanları, yani namespace yapıları, bu isimleri mantıksal gruplara ayırarak derleyiciye hangi varlığı kastettiğimizi söyler. Kısacası namespace, kod dünyasının mahalle adresidir: Aynı isimli iki kişi olabilir, yeter ki farklı adreslerde yaşasın!]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/c-isim-alanlari-19.png" /><media:content medium="image" url="https://program.sonsuz.us/img/c-isim-alanlari-19.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>