<?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-21T00:05:47+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">Arduino ve Raspberry Pi ile Robotik Eğitimi Herkes İçin Erişilebilir</title><link href="https://program.sonsuz.us/posts/arduino-ve-raspberry-pi-ile-robotik-egitimi-herkes-icin-erisilebilir/" rel="alternate" type="text/html" title="Arduino ve Raspberry Pi ile Robotik Eğitimi Herkes İçin Erişilebilir" /><published>2026-10-20T00:00:00+00:00</published><updated>2026-10-20T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/arduino-ve-raspberry-pi-ile-robotik-egitimi-herkes-icin-erisilebilir</id><content type="html" xml:base="https://program.sonsuz.us/posts/arduino-ve-raspberry-pi-ile-robotik-egitimi-herkes-icin-erisilebilir/"><![CDATA[<p>Bir zamanlar robot geliştirmek; pahalı laboratuvarlara, özel üretim devrelere ve kalın mühendislik kitaplarına erişmeyi gerektiriyordu. Arduino ve Raspberry Pi gibi açık kaynaklı donanım platformları ise bu tabloyu önemli ölçüde değiştirdi. Öğrenciler artık birkaç sensör, motor ve internetten erişilebilen örneklerle çalışan bir robot geliştirebiliyor. Böylece robotik eğitimi, yalnızca uzmanların bulunduğu laboratuvarlardan çıkarak sınıflara, atölyelere ve hatta mutfak masalarına kadar ulaşıyor.</p>

<p>``</p>

<h2 id="açık-kaynak-erişilebilirliği-nasıl-artırıyor">Açık kaynak erişilebilirliği nasıl artırıyor?</h2>

<p>Açık kaynaklı donanımda devre şemaları, yazılım araçları, kütüphaneler ve örnek projeler toplulukla paylaşılır. Kullanıcı yalnızca hazır bir ürünü tüketmez; sistemin nasıl çalıştığını inceleyebilir, değiştirebilir ve yeniden üretebilir. Bu yaklaşım erişilebilirliği üç yönden güçlendirir:</p>

<ul>
  <li><strong>Ekonomik erişim:</strong> Düşük maliyetli kartlar ve uyumlu yan ürünler kullanılabilir.</li>
  <li><strong>Bilgiye erişim:</strong> Ücretsiz belgeler, videolar ve topluluk forumları öğrenme sürecini destekler.</li>
  <li><strong>Deneysel erişim:</strong> Öğrenci, hata yapmaktan korkmadan devreyi ve kodu değiştirebilir.</li>
</ul>

<p>Robotik sistemlerin temelinde algılama, karar verme ve hareket etme döngüsü bulunur. Sensör çevreden veri toplar, kontrol birimi bu veriyi işler ve aktüatörler fiziksel tepki üretir:</p>

\[Algılama \rightarrow Karar \rightarrow Hareket\]

<p>Örneğin ultrasonik sensörün gönderdiği ses dalgasının geri dönüş süresi $t$, ses hızı $v$ ve engel uzaklığı $d$ arasındaki ilişki şöyledir:</p>

\[d = \frac{v \cdot t}{2}\]

<p>İkiye bölünmesinin nedeni, ölçülen sürenin sesin engele gidişini ve geri dönüşünü birlikte içermesidir. Böyle bir formül, fizik bilgisini doğrudan çalışan bir robot üzerinde görünür hâle getirir.</p>

<h2 id="arduino-mu-raspberry-pi-mı">Arduino mu, Raspberry Pi mı?</h2>

<p>Her iki platform da robotik eğitiminde değerlidir; ancak aynı işi yapmak üzere tasarlanmamıştır.</p>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Arduino</th>
      <th>Raspberry Pi</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Yapı</td>
      <td>Mikrodenetleyici kartı</td>
      <td>Tek kart bilgisayar</td>
    </tr>
    <tr>
      <td>İşletim sistemi</td>
      <td>Yok</td>
      <td>Genellikle Linux</td>
    </tr>
    <tr>
      <td>Başlangıç süresi</td>
      <td>Neredeyse anlık</td>
      <td>İşletim sistemi açılışı gerekir</td>
    </tr>
    <tr>
      <td>Güç tüketimi</td>
      <td>Düşük</td>
      <td>Daha yüksek</td>
    </tr>
    <tr>
      <td>Uygun görevler</td>
      <td>Sensör, motor, gerçek zamanlı kontrol</td>
      <td>Görüntü işleme, yapay zekâ, ağ uygulamaları</td>
    </tr>
    <tr>
      <td>Başlangıç zorluğu</td>
      <td>Elektronik odaklı ve sade</td>
      <td>Yazılım olanakları geniş, yapılandırması daha ayrıntılı</td>
    </tr>
  </tbody>
</table>

<p><img src="/img/arduino-ve-raspberry-56.svg" alt="arduino-ve-raspberry-56" /></p>

<p>Arduino, çizgi izleyen veya engelden kaçan bir robot için güçlü bir başlangıçtır. Raspberry Pi ise kamera görüntüsünden nesne tanıyan ya da web arayüzüyle yönetilen robotlarda öne çıkar. İki kart birlikte de kullanılabilir: Raspberry Pi yüksek seviyeli kararları verirken Arduino motorları zamanlamaya duyarlı biçimde kontrol edebilir.</p>

<h2 id="küçük-bir-robot-refleksi">Küçük bir robot refleksi</h2>

<p>Aşağıdaki Arduino kodu, bir dijital sensör engel algıladığında motor kontrol çıkışını durdurur. Bu örnek, algılama-karar-hareket döngüsünün en sade hâlidir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">const</span> <span class="kt">int</span> <span class="n">sensorPin</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="k">const</span> <span class="kt">int</span> <span class="n">motorPin</span> <span class="o">=</span> <span class="mi">9</span><span class="p">;</span>

<span class="kt">void</span> <span class="nf">setup</span><span class="p">()</span> <span class="p">{</span>
  <span class="n">pinMode</span><span class="p">(</span><span class="n">sensorPin</span><span class="p">,</span> <span class="n">INPUT</span><span class="p">);</span>
  <span class="n">pinMode</span><span class="p">(</span><span class="n">motorPin</span><span class="p">,</span> <span class="n">OUTPUT</span><span class="p">);</span>
<span class="p">}</span>

<span class="kt">void</span> <span class="nf">loop</span><span class="p">()</span> <span class="p">{</span>
  <span class="kt">bool</span> <span class="n">engelVar</span> <span class="o">=</span> <span class="n">digitalRead</span><span class="p">(</span><span class="n">sensorPin</span><span class="p">);</span>

  <span class="k">if</span> <span class="p">(</span><span class="n">engelVar</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">analogWrite</span><span class="p">(</span><span class="n">motorPin</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>    <span class="c1">// Motoru durdur</span>
  <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
    <span class="n">analogWrite</span><span class="p">(</span><span class="n">motorPin</span><span class="p">,</span> <span class="mi">180</span><span class="p">);</span>  <span class="c1">// Orta-yüksek hızda ilerle</span>
  <span class="p">}</span>

  <span class="n">delay</span><span class="p">(</span><span class="mi">20</span><span class="p">);</span> <span class="c1">// Sensörü saniyede yaklaşık 50 kez kontrol et</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Kod yalnızca programlamayı değil, giriş-çıkış mantığını ve geri beslemeyi de öğretir. Öğrenci <code class="language-plaintext highlighter-rouge">180</code> değerini değiştirerek hızın davranışa etkisini gözlemleyebilir. Elbette gerçek bir motor doğrudan karta bağlanmamalı; motor sürücü devresi ve uygun güç kaynağı kullanılmalıdır.</p>

<h2 id="erişilebilirlik-yalnızca-düşük-fiyat-değildir">Erişilebilirlik yalnızca düşük fiyat değildir</h2>

<p>Ucuz kartlar tek başına eşit eğitim fırsatı oluşturmaz. İnternet erişimi, yerelleştirilmiş içerik, öğretmen eğitimi, yedek parça bulunabilirliği ve güvenli çalışma ortamı da önemlidir. Ayrıca açık kaynak projelerde belgelerin güncelliği değişebilir ve Raspberry Pi gibi kartların toplam maliyetine güç kaynağı, hafıza kartı ve çevre birimleri eklenebilir.</p>

<p>Buna rağmen bu platformların en büyük katkısı, öğrenciyi pasif kullanıcıdan üreticiye dönüştürmesidir. Bir LED’i yakmakla başlayan yolculuk; otonom araçlara, tarım robotlarına veya yapay zekâ destekli sistemlere uzanabilir. Robotik böylece ulaşılmaz bir gelecek teknolojisi değil, parçalarına ayrılıp anlaşılabilen ve yeniden tasarlanabilen bir öğrenme alanı hâline gelir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="arduino" /><category term="raspberry pi" /><category term="robotik" /><category term="açık kaynak" /><category term="stem" /><category term="elektronik" /><summary type="html"><![CDATA[Bir zamanlar robot geliştirmek; pahalı laboratuvarlara, özel üretim devrelere ve kalın mühendislik kitaplarına erişmeyi gerektiriyordu. Arduino ve Raspberry Pi gibi açık kaynaklı donanım platformları ise bu tabloyu önemli ölçüde değiştirdi. Öğrenciler artık birkaç sensör, motor ve internetten erişilebilen örneklerle çalışan bir robot geliştirebiliyor. Böylece robotik eğitimi, yalnızca uzmanların bulunduğu laboratuvarlardan çıkarak sınıflara, atölyelere ve hatta mutfak masalarına kadar ulaşıyor.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/arduino-ve-raspberry-56.png" /><media:content medium="image" url="https://program.sonsuz.us/img/arduino-ve-raspberry-56.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">C Dosya İşlemleri: Stream’lerle Kalıcı Veri Okuma ve Yazma</title><link href="https://program.sonsuz.us/posts/c-dosya-islemleri-streamlerle-kalici-veri-okuma-ve-yazma/" rel="alternate" type="text/html" title="C Dosya İşlemleri: Stream’lerle Kalıcı Veri Okuma ve Yazma" /><published>2026-10-20T00:00:00+00:00</published><updated>2026-10-20T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/c-dosya-islemleri-streamlerle-kalici-veri-okuma-ve-yazma</id><content type="html" xml:base="https://program.sonsuz.us/posts/c-dosya-islemleri-streamlerle-kalici-veri-okuma-ve-yazma/"><![CDATA[<p>Bir C programı çalışırken değişkenler çoğunlukla RAM’de yaşar ve program sonlandığında sahneden sessizce çekilir. Oysa kullanıcı kayıtları, ayarlar veya ölçüm sonuçları gibi verilerin yeniden kullanılabilmesi için diske yazılması gerekir. C’nin File I/O araçları, geçici bellek ile kalıcı depolama arasında bir köprü kurar.</p>

<p>``</p>

<h2 id="stream-mantığı-nedir">Stream mantığı nedir?</h2>

<p>C, dosya ve aygıtlarla iletişimi <strong>stream</strong>, yani veri akışı soyutlaması üzerinden gerçekleştirir. Program açısından stream, sırayla okunabilen veya yazılabilen karakter ve bayt dizisidir. Bunun arkasında SSD, terminal ya da başka bir aygıt bulunabilir; temel işlemler büyük ölçüde aynı kalır.</p>

<p><code class="language-plaintext highlighter-rouge">&lt;stdio.h&gt;</code> kütüphanesindeki <code class="language-plaintext highlighter-rouge">FILE</code> yapısı bir stream’i temsil eder. Bu yapı dosyanın konumu, erişim modu, tampon bilgisi ve hata durumu gibi ayrıntıları yönetir. Genellikle yapının iç alanlarına doğrudan dokunulmaz; onun yerine <code class="language-plaintext highlighter-rouge">fopen</code>, <code class="language-plaintext highlighter-rouge">fclose</code>, <code class="language-plaintext highlighter-rouge">fprintf</code> ve <code class="language-plaintext highlighter-rouge">fread</code> gibi fonksiyonlar kullanılır.</p>

<p>Bir dosyanın toplam boyutu kabaca</p>

\[S = n \times b\]

<p>ile düşünülebilir. Burada $n$ kayıt sayısını, $b$ ise her kaydın bayt cinsinden ortalama boyutunu gösterir. Metin dosyalarında karakter kodlaması ve ayraçlar nedeniyle gerçek boyut değişebilir.</p>

<p>C programları açıldığında üç standart stream hazırdır:</p>

<table>
  <thead>
    <tr>
      <th>Stream</th>
      <th>Görevi</th>
      <th>Varsayılan aygıt</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">stdin</code></td>
      <td>Veri okumak</td>
      <td>Klavye</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">stdout</code></td>
      <td>Normal çıktı yazmak</td>
      <td>Terminal</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">stderr</code></td>
      <td>Hata mesajı yazmak</td>
      <td>Terminal</td>
    </tr>
  </tbody>
</table>

<h2 id="dosya-açma-modları">Dosya açma modları</h2>

<p>Dosya işlemi, <code class="language-plaintext highlighter-rouge">fopen</code> ile bir stream açarak başlar. Fonksiyon başarısız olursa <code class="language-plaintext highlighter-rouge">NULL</code> döndürür; bu kontrolü atlamak, programı hata festivaline dönüştürebilir.</p>

<table>
  <thead>
    <tr>
      <th>Mod</th>
      <th>Anlamı</th>
      <th>Dosya yoksa</th>
      <th>Mevcut içerik</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">r</code></td>
      <td>Okuma</td>
      <td>Hata</td>
      <td>Korunur</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">w</code></td>
      <td>Yazma</td>
      <td>Oluşturulur</td>
      <td>Silinir</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">a</code></td>
      <td>Sona ekleme</td>
      <td>Oluşturulur</td>
      <td>Korunur</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">r+</code></td>
      <td>Okuma ve yazma</td>
      <td>Hata</td>
      <td>Korunur</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">w+</code></td>
      <td>Okuma ve yazma</td>
      <td>Oluşturulur</td>
      <td>Silinir</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">a+</code></td>
      <td>Okuma ve sona ekleme</td>
      <td>Oluşturulur</td>
      <td>Korunur</td>
    </tr>
  </tbody>
</table>

<p>İkili dosyalarda moda <code class="language-plaintext highlighter-rouge">b</code> eklenebilir: <code class="language-plaintext highlighter-rouge">rb</code>, <code class="language-plaintext highlighter-rouge">wb</code> veya <code class="language-plaintext highlighter-rouge">ab</code> gibi.</p>

<h2 id="metin-dosyasına-yazma-ve-okuma">Metin dosyasına yazma ve okuma</h2>

<p>Aşağıdaki örnek, bir puanı dosyaya yazar ve ardından geri okur:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
    <span class="kt">FILE</span> <span class="o">*</span><span class="n">dosya</span> <span class="o">=</span> <span class="n">fopen</span><span class="p">(</span><span class="s">"puan.txt"</span><span class="p">,</span> <span class="s">"w"</span><span class="p">);</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">dosya</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">perror</span><span class="p">(</span><span class="s">"Dosya acilamadi"</span><span class="p">);</span>
        <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="n">fprintf</span><span class="p">(</span><span class="n">dosya</span><span class="p">,</span> <span class="s">"%s %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="s">"Ada"</span><span class="p">,</span> <span class="mi">95</span><span class="p">);</span>
    <span class="n">fclose</span><span class="p">(</span><span class="n">dosya</span><span class="p">);</span>

    <span class="n">dosya</span> <span class="o">=</span> <span class="n">fopen</span><span class="p">(</span><span class="s">"puan.txt"</span><span class="p">,</span> <span class="s">"r"</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">dosya</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">perror</span><span class="p">(</span><span class="s">"Dosya okunamadi"</span><span class="p">);</span>
        <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="kt">char</span> <span class="n">isim</span><span class="p">[</span><span class="mi">32</span><span class="p">];</span>
    <span class="kt">int</span> <span class="n">puan</span><span class="p">;</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">fscanf</span><span class="p">(</span><span class="n">dosya</span><span class="p">,</span> <span class="s">"%31s %d"</span><span class="p">,</span> <span class="n">isim</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">puan</span><span class="p">)</span> <span class="o">==</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"Ogrenci: %s, puan: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">isim</span><span class="p">,</span> <span class="n">puan</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="n">fclose</span><span class="p">(</span><span class="n">dosya</span><span class="p">);</span>
    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">fprintf</code>, biçimlendirilmiş veriyi stream’e gönderir. <code class="language-plaintext highlighter-rouge">fscanf</code> ise veriyi belirtilen formata göre ayrıştırır. <code class="language-plaintext highlighter-rouge">%31s</code> sınırı, 32 elemanlı dizide taşmayı önlemek için en fazla 31 karakter okur. Her açılan dosyanın <code class="language-plaintext highlighter-rouge">fclose</code> ile kapatılması tamponlanmış verilerin diske aktarılmasını ve sistem kaynaklarının serbest bırakılmasını sağlar.</p>

<h2 id="metin-mi-ikili-dosya-mı">Metin mi, ikili dosya mı?</h2>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Metin dosyası</th>
      <th>İkili dosya</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Okunabilirlik</td>
      <td>İnsan tarafından kolay okunur</td>
      <td>Özel araç gerekebilir</td>
    </tr>
    <tr>
      <td>Boyut</td>
      <td>Genellikle daha büyük</td>
      <td>Genellikle daha küçük</td>
    </tr>
    <tr>
      <td>Taşınabilirlik</td>
      <td>Yüksek</td>
      <td>Veri tiplerine bağlı</td>
    </tr>
    <tr>
      <td>Fonksiyonlar</td>
      <td><code class="language-plaintext highlighter-rouge">fprintf</code>, <code class="language-plaintext highlighter-rouge">fgets</code></td>
      <td><code class="language-plaintext highlighter-rouge">fwrite</code>, <code class="language-plaintext highlighter-rouge">fread</code></td>
    </tr>
  </tbody>
</table>

<p>İkili yazmada temel denklem aktarılan bayt miktarı için $B = adet \times sizeof(tür)$ biçimindedir. Örneğin <code class="language-plaintext highlighter-rouge">fwrite(dizi, sizeof(int), 10, dosya)</code> on tamsayıyı yazar.</p>

<p>Son olarak <code class="language-plaintext highlighter-rouge">feof</code> akış sonunu, <code class="language-plaintext highlighter-rouge">ferror</code> ise okuma veya yazma hatasını denetler. Sağlam bir File I/O kodu yalnızca mutlu senaryoyu değil; eksik dosyayı, bozuk veriyi ve başarısız yazmayı da hesaba katar. Böylece veriler program kapandığında buharlaşmak yerine diskte güvenle yaşamaya devam eder.</p>

<p><img src="/img/c-dosya-islemleri-83.svg" alt="c-dosya-islemleri-83" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="c" /><category term="dosya işlemleri" /><category term="file io" /><category term="stream" /><category term="stdio" /><category term="programlama" /><summary type="html"><![CDATA[Bir C programı çalışırken değişkenler çoğunlukla RAM’de yaşar ve program sonlandığında sahneden sessizce çekilir. Oysa kullanıcı kayıtları, ayarlar veya ölçüm sonuçları gibi verilerin yeniden kullanılabilmesi için diske yazılması gerekir. C’nin File I/O araçları, geçici bellek ile kalıcı depolama arasında bir köprü kurar.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/c-dosya-islemleri-83.png" /><media:content medium="image" url="https://program.sonsuz.us/img/c-dosya-islemleri-83.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">C# ile Multithreading: TPL, Task ve async/await Rehberi</title><link href="https://program.sonsuz.us/posts/c-ile-multithreading-tpl-task-ve-asyncawait-rehberi/" rel="alternate" type="text/html" title="C# ile Multithreading: TPL, Task ve async/await Rehberi" /><published>2026-10-20T00:00:00+00:00</published><updated>2026-10-20T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/c-ile-multithreading-tpl-task-ve-asyncawait-rehberi</id><content type="html" xml:base="https://program.sonsuz.us/posts/c-ile-multithreading-tpl-task-ve-asyncawait-rehberi/"><![CDATA[<p>Bir uygulamanın aynı anda birden fazla iş yapabilmesi kulağa sihir gibi gelebilir; ancak C# dünyasında bu sihrin arkasında iş parçacıkları, görevler ve dikkatli bir zamanlama mekanizması bulunur. Task Parallel Library (TPL) CPU ağırlıklı işleri paralelleştirirken <code class="language-plaintext highlighter-rouge">async/await</code>, özellikle dosya, ağ ve veritabanı gibi beklemeli işlemlerde iş parçacıklarını gereksiz yere meşgul etmeden ölçeklenebilir uygulamalar kurmamızı sağlar.
``</p>
<h2 id="eşzamanlılık-ve-paralellik-aynı-şey-değildir">Eşzamanlılık ve paralellik aynı şey değildir</h2>

<p>Eşzamanlılık, birden fazla işin zaman aralıkları iç içe geçecek şekilde ilerlemesidir. Paralellik ise bu işlerin gerçekten aynı anda, örneğin farklı işlemci çekirdeklerinde çalışmasıdır.</p>

<table>
  <thead>
    <tr>
      <th>Kavram</th>
      <th>Temel amaç</th>
      <th>Uygun iş türü</th>
      <th>C# aracı</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Eşzamanlılık</td>
      <td>Beklerken başka işe geçmek</td>
      <td>Ağ, dosya, veritabanı</td>
      <td><code class="language-plaintext highlighter-rouge">async/await</code></td>
    </tr>
    <tr>
      <td>Paralellik</td>
      <td>Hesabı çekirdeklere dağıtmak</td>
      <td>Görüntü işleme, hesaplama</td>
      <td><code class="language-plaintext highlighter-rouge">Parallel</code>, TPL</td>
    </tr>
    <tr>
      <td>İş parçacığı</td>
      <td>Çalıştırma kaynağı sağlamak</td>
      <td>Düşük seviyeli kontrol</td>
      <td><code class="language-plaintext highlighter-rouge">Thread</code></td>
    </tr>
    <tr>
      <td>Görev</td>
      <td>Yapılacak işi temsil etmek</td>
      <td>Modern iş akışları</td>
      <td><code class="language-plaintext highlighter-rouge">Task</code></td>
    </tr>
  </tbody>
</table>

<p>Bir işin tek çekirdekte tamamlanma süresi $T_1$, $p$ çekirdekteki süresi $T_p$ ise teorik hızlanma şöyle ifade edilir:</p>

\[S_p = \frac{T_1}{T_p}\]

<p>İdeal durumda $S_p \approx p$ beklenir. Gerçekte görev oluşturma maliyeti, senkronizasyon ve paylaşılan kaynaklar nedeniyle bu değere nadiren ulaşılır.</p>

<h2 id="tpl-ile-cpu-ağırlıklı-işleri-çalıştırmak">TPL ile CPU ağırlıklı işleri çalıştırmak</h2>

<p>TPL, görevlerin uygun iş parçacıklarına dağıtılmasını <code class="language-plaintext highlighter-rouge">ThreadPool</code> üzerinden yönetir. Böylece her iş için elle <code class="language-plaintext highlighter-rouge">Thread</code> oluşturmak gerekmez.</p>

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

<span class="kt">int</span><span class="p">[]</span> <span class="n">sayilar</span> <span class="p">=</span> <span class="n">Enumerable</span><span class="p">.</span><span class="nf">Range</span><span class="p">(</span><span class="m">1</span><span class="p">,</span> <span class="m">8</span><span class="p">).</span><span class="nf">ToArray</span><span class="p">();</span>

<span class="n">Parallel</span><span class="p">.</span><span class="nf">ForEach</span><span class="p">(</span><span class="n">sayilar</span><span class="p">,</span> <span class="n">sayi</span> <span class="p">=&gt;</span>
<span class="p">{</span>
    <span class="kt">double</span> <span class="n">sonuc</span> <span class="p">=</span> <span class="n">Math</span><span class="p">.</span><span class="nf">Sqrt</span><span class="p">(</span><span class="n">sayi</span><span class="p">)</span> <span class="p">*</span> <span class="n">Math</span><span class="p">.</span><span class="nf">Pow</span><span class="p">(</span><span class="n">sayi</span><span class="p">,</span> <span class="m">3</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">$"</span><span class="p">{</span><span class="n">sayi</span><span class="p">}</span><span class="s">: </span><span class="p">{</span><span class="n">sonuc</span><span class="p">}</span><span class="s"> - Thread: </span><span class="p">{</span><span class="n">Environment</span><span class="p">.</span><span class="n">CurrentManagedThreadId</span><span class="p">}</span><span class="s">"</span><span class="p">);</span>
<span class="p">});</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">Parallel.ForEach</code>, koleksiyondaki hesaplamaları mümkün olduğunda farklı iş parçacıklarında yürütür. Ancak çok küçük işlemleri paralelleştirmek, yönetim maliyeti yüzünden normal bir döngüden daha yavaş olabilir. Önce ölçmek, sonra paralelleştirmek altın kuraldır.</p>

<p>Bağımsız görevleri başlatıp hepsinin bitmesini beklemek için <code class="language-plaintext highlighter-rouge">Task.WhenAll</code> kullanılabilir:</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Task</span><span class="p">&lt;</span><span class="kt">int</span><span class="p">&gt;</span> <span class="n">hesap1</span> <span class="p">=</span> <span class="n">Task</span><span class="p">.</span><span class="nf">Run</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="n">Enumerable</span><span class="p">.</span><span class="nf">Range</span><span class="p">(</span><span class="m">1</span><span class="p">,</span> <span class="m">1_000_000</span><span class="p">).</span><span class="nf">Sum</span><span class="p">());</span>
<span class="n">Task</span><span class="p">&lt;</span><span class="kt">int</span><span class="p">&gt;</span> <span class="n">hesap2</span> <span class="p">=</span> <span class="n">Task</span><span class="p">.</span><span class="nf">Run</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="n">Enumerable</span><span class="p">.</span><span class="nf">Range</span><span class="p">(</span><span class="m">1</span><span class="p">,</span> <span class="m">500_000</span><span class="p">).</span><span class="nf">Sum</span><span class="p">());</span>

<span class="kt">int</span><span class="p">[]</span> <span class="n">sonuclar</span> <span class="p">=</span> <span class="k">await</span> <span class="n">Task</span><span class="p">.</span><span class="nf">WhenAll</span><span class="p">(</span><span class="n">hesap1</span><span class="p">,</span> <span class="n">hesap2</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">$"Toplam: </span><span class="p">{</span><span class="n">sonuclar</span><span class="p">.</span><span class="nf">Sum</span><span class="p">()}</span><span class="s">"</span><span class="p">);</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">Task.Run</code>, CPU ağırlıklı senkron kodu ThreadPool üzerinde çalıştırır. Buna karşılık zaten asenkron olan HTTP veya veritabanı çağrılarını ayrıca <code class="language-plaintext highlighter-rouge">Task.Run</code> içine koymak genellikle gereksizdir.</p>

<h2 id="asyncawait-ile-beklerken-kaynak-tüketmemek">async/await ile beklerken kaynak tüketmemek</h2>

<p><code class="language-plaintext highlighter-rouge">async</code>, metodun asenkron işlem içerebildiğini; <code class="language-plaintext highlighter-rouge">await</code> ise işlem tamamlanana kadar kontrolün çağırana geri verilebileceğini belirtir. Bu sırada iş parçacığının bloklanması gerekmez.</p>

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

<span class="k">static</span> <span class="k">async</span> <span class="n">Task</span><span class="p">&lt;</span><span class="kt">int</span><span class="p">&gt;</span> <span class="nf">SayfaBoyutuAsync</span><span class="p">(</span>
    <span class="kt">string</span> <span class="n">adres</span><span class="p">,</span>
    <span class="n">CancellationToken</span> <span class="n">iptal</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">using</span> <span class="nn">HttpClient</span> <span class="n">istemci</span> <span class="p">=</span> <span class="k">new</span><span class="p">();</span>
    <span class="kt">string</span> <span class="n">icerik</span> <span class="p">=</span> <span class="k">await</span> <span class="n">istemci</span><span class="p">.</span><span class="nf">GetStringAsync</span><span class="p">(</span><span class="n">adres</span><span class="p">,</span> <span class="n">iptal</span><span class="p">);</span>
    <span class="k">return</span> <span class="n">icerik</span><span class="p">.</span><span class="n">Length</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">using</span> <span class="nn">CancellationTokenSource</span> <span class="n">kaynak</span> <span class="p">=</span> <span class="k">new</span><span class="p">();</span>
<span class="n">kaynak</span><span class="p">.</span><span class="nf">CancelAfter</span><span class="p">(</span><span class="n">TimeSpan</span><span class="p">.</span><span class="nf">FromSeconds</span><span class="p">(</span><span class="m">5</span><span class="p">));</span>

<span class="k">try</span>
<span class="p">{</span>
    <span class="kt">int</span> <span class="n">boyut</span> <span class="p">=</span> <span class="k">await</span> <span class="nf">SayfaBoyutuAsync</span><span class="p">(</span><span class="s">"https://example.com"</span><span class="p">,</span> <span class="n">kaynak</span><span class="p">.</span><span class="n">Token</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">$"İndirilen karakter: </span><span class="p">{</span><span class="n">boyut</span><span class="p">}</span><span class="s">"</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">catch</span> <span class="p">(</span><span class="n">OperationCanceledException</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="s">"İşlem iptal edildi."</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Buradaki <code class="language-plaintext highlighter-rouge">CancellationToken</code>, uzun süren işlemin kontrollü biçimde durdurulmasını sağlar. <code class="language-plaintext highlighter-rouge">await</code> edilen görev hata üretirse istisna normal bir senkron metottaki gibi <code class="language-plaintext highlighter-rouge">try/catch</code> ile yakalanabilir.</p>

<h2 id="paylaşılan-veriler-ve-yarış-durumları">Paylaşılan veriler ve yarış durumları</h2>

<p>Birden fazla görev aynı değişkeni değiştirirse sonuç öngörülemez olabilir. Örneğin <code class="language-plaintext highlighter-rouge">sayac++</code> atomik değildir; okuma, artırma ve yazma adımlarından oluşur. Güvenli artırma için <code class="language-plaintext highlighter-rouge">Interlocked.Increment(ref sayac)</code> veya daha karmaşık kritik bölgelerde <code class="language-plaintext highlighter-rouge">lock</code> kullanılmalıdır.</p>

<p>Modern C# kodunda temel yaklaşım basittir: I/O ağırlıklı işlemlerde doğal asenkron API’leri <code class="language-plaintext highlighter-rouge">await</code> edin, CPU ağırlıklı ve bağımsız hesaplamalarda TPL kullanın, paylaşılan durumu azaltın ve performans kararlarını mutlaka ölçümlerle doğrulayın.</p>

<p><img src="/img/c-ile-multithreading-31.svg" alt="c-ile-multithreading-31" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Program" /><category term="csharp" /><category term="multithreading" /><category term="tpl" /><category term="async" /><category term="await" /><category term="paralel-programlama" /><summary type="html"><![CDATA[Bir uygulamanın aynı anda birden fazla iş yapabilmesi kulağa sihir gibi gelebilir; ancak C# dünyasında bu sihrin arkasında iş parçacıkları, görevler ve dikkatli bir zamanlama mekanizması bulunur. Task Parallel Library (TPL) CPU ağırlıklı işleri paralelleştirirken async/await, özellikle dosya, ağ ve veritabanı gibi beklemeli işlemlerde iş parçacıklarını gereksiz yere meşgul etmeden ölçeklenebilir uygulamalar kurmamızı sağlar.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/c-ile-multithreading-31.png" /><media:content medium="image" url="https://program.sonsuz.us/img/c-ile-multithreading-31.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">C++ RTTI ve Güvenli Tür Dönüşümleri: Nesnenin Gerçek Kimliğini Bulmak</title><link href="https://program.sonsuz.us/posts/c-rtti-ve-guvenli-tur-donusumleri-nesnenin-gercek-kimligini-bulmak/" rel="alternate" type="text/html" title="C++ RTTI ve Güvenli Tür Dönüşümleri: Nesnenin Gerçek Kimliğini Bulmak" /><published>2026-10-20T00:00:00+00:00</published><updated>2026-10-20T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/c-rtti-ve-guvenli-tur-donusumleri-nesnenin-gercek-kimligini-bulmak</id><content type="html" xml:base="https://program.sonsuz.us/posts/c-rtti-ve-guvenli-tur-donusumleri-nesnenin-gercek-kimligini-bulmak/"><![CDATA[<p><img src="/img/c-rtti-ve-63.svg" alt="c-rtti-ve-63" /></p>

<p>C++ dünyasında bir nesne her zaman göründüğü şey olmayabilir. Elinizde <code class="language-plaintext highlighter-rouge">Karakter*</code> türünde bir işaretçi bulunurken, işaret edilen gerçek nesne bir <code class="language-plaintext highlighter-rouge">Buyucu</code> veya <code class="language-plaintext highlighter-rouge">Savasci</code> olabilir. Çalışma Zamanı Tür Bilgisi, yani RTTI (Run-Time Type Information), program çalışırken bu gerçek kimliği öğrenmemizi ve kalıtım hiyerarşilerinde güvenli dönüşümler yapmamızı sağlar.
``</p>

<h2 id="rtti-neden-gereklidir">RTTI neden gereklidir?</h2>

<p>C++ değişkenlerinin çoğu tür bilgisi derleme zamanında bellidir. Ancak polimorfizm kullanıldığında statik tür ile dinamik tür birbirinden ayrılır:</p>

<ul>
  <li><strong>Statik tür:</strong> Değişkenin kaynak kodunda bildirilen türdür.</li>
  <li><strong>Dinamik tür:</strong> Çalışma anında gerçekten oluşturulmuş nesnenin türüdür.</li>
</ul>

<p>Bir <code class="language-plaintext highlighter-rouge">Karakter*</code> değişkeninin statik türü <code class="language-plaintext highlighter-rouge">Karakter*</code>, gösterdiği nesne <code class="language-plaintext highlighter-rouge">Buyucu</code> ise dinamik türü <code class="language-plaintext highlighter-rouge">Buyucu</code> olur. Bunu kabaca şu ilişkiyle gösterebiliriz:</p>

\[T_{statik} \neq T_{dinamik}\]

<p>RTTI özellikle taban sınıf üzerinden yönetilen nesnelerin alt sınıflarını ayırt etmek gerektiğinde devreye girer. Bunun çalışabilmesi için taban sınıfın <strong>polimorfik</strong> olması, yani en az bir sanal (<code class="language-plaintext highlighter-rouge">virtual</code>) fonksiyon içermesi gerekir. Genellikle sanal yıkıcı tanımlamak yeterlidir.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Karakter</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="k">virtual</span> <span class="o">~</span><span class="n">Karakter</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">class</span> <span class="nc">Buyucu</span> <span class="o">:</span> <span class="k">public</span> <span class="n">Karakter</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="kt">void</span> <span class="n">buyuYap</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="s">"Ateş topu!</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<p>Sanal yıkıcı hem RTTI kullanımını mümkün kılar hem de nesne taban sınıf işaretçisi üzerinden silindiğinde doğru yıkıcının çağrılmasını sağlar.</p>

<h2 id="typeid-ile-türü-incelemek"><code class="language-plaintext highlighter-rouge">typeid</code> ile türü incelemek</h2>

<p><code class="language-plaintext highlighter-rouge">typeid</code> operatörü bir ifade veya tür hakkında <code class="language-plaintext highlighter-rouge">std::type_info</code> nesnesi döndürür. İki türün aynı olup olmadığı güvenilir biçimde karşılaştırılabilir:</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;typeinfo&gt;</span><span class="cp">
</span>
<span class="n">Karakter</span><span class="o">*</span> <span class="n">karakter</span> <span class="o">=</span> <span class="k">new</span> <span class="nf">Buyucu</span><span class="p">();</span>

<span class="k">if</span> <span class="p">(</span><span class="k">typeid</span><span class="p">(</span><span class="o">*</span><span class="n">karakter</span><span class="p">)</span> <span class="o">==</span> <span class="k">typeid</span><span class="p">(</span><span class="n">Buyucu</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="s">"Bu karakter gerçekten bir büyücü.</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">delete</span> <span class="n">karakter</span><span class="p">;</span>
</code></pre></div></div>

<p>Burada <code class="language-plaintext highlighter-rouge">typeid(*karakter)</code> dinamik türü bulur. Buna karşılık <code class="language-plaintext highlighter-rouge">typeid(karakter)</code> işaretçinin kendi türünü, yani <code class="language-plaintext highlighter-rouge">Karakter*</code> türünü verir. <code class="language-plaintext highlighter-rouge">type_info::name()</code> da kullanılabilir; ancak döndürdüğü metnin biçimi derleyiciye bağlıdır ve program mantığı için güvenilir değildir.</p>

<h2 id="dynamic_cast-ile-güvenli-dönüşüm"><code class="language-plaintext highlighter-rouge">dynamic_cast</code> ile güvenli dönüşüm</h2>

<p><code class="language-plaintext highlighter-rouge">dynamic_cast</code>, polimorfik kalıtım hiyerarşilerinde çalışma zamanı kontrolü yapar. İşaretçi dönüşümü başarısız olursa <code class="language-plaintext highlighter-rouge">nullptr</code> döndürür:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Karakter</span><span class="o">*</span> <span class="n">karakter</span> <span class="o">=</span> <span class="k">new</span> <span class="nf">Buyucu</span><span class="p">();</span>

<span class="k">if</span> <span class="p">(</span><span class="n">Buyucu</span><span class="o">*</span> <span class="n">buyucu</span> <span class="o">=</span> <span class="k">dynamic_cast</span><span class="o">&lt;</span><span class="n">Buyucu</span><span class="o">*&gt;</span><span class="p">(</span><span class="n">karakter</span><span class="p">))</span> <span class="p">{</span>
    <span class="n">buyucu</span><span class="o">-&gt;</span><span class="n">buyuYap</span><span class="p">();</span>
<span class="p">}</span> <span class="k">else</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">"Bu karakter büyü yapamaz.</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
<span class="p">}</span>

 <span class="k">delete</span> <span class="n">karakter</span><span class="p">;</span>
</code></pre></div></div>

<p>Referanslarda başarısızlık <code class="language-plaintext highlighter-rouge">nullptr</code> ile bildirilemez. Bu nedenle <code class="language-plaintext highlighter-rouge">dynamic_cast&lt;Buyucu&amp;&gt;</code> başarısız olduğunda <code class="language-plaintext highlighter-rouge">std::bad_cast</code> istisnası fırlatır.</p>

<h2 id="dönüşüm-araçlarının-karşılaştırması">Dönüşüm araçlarının karşılaştırması</h2>

<table>
  <thead>
    <tr>
      <th>Araç</th>
      <th>Kontrol zamanı</th>
      <th>Başarısızlık davranışı</th>
      <th>Tipik kullanım</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">dynamic_cast</code></td>
      <td>Çalışma zamanı</td>
      <td><code class="language-plaintext highlighter-rouge">nullptr</code> veya <code class="language-plaintext highlighter-rouge">std::bad_cast</code></td>
      <td>Güvenli aşağı dönüşüm</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">static_cast</code></td>
      <td>Derleme zamanı</td>
      <td>Otomatik güvenlik kontrolü yok</td>
      <td>Bilinen ve mantıksal dönüşümler</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">const_cast</code></td>
      <td>Derleme zamanı</td>
      <td><code class="language-plaintext highlighter-rouge">const</code> niteliğini değiştirir</td>
      <td>Eski API uyumluluğu</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">reinterpret_cast</code></td>
      <td>Derleme zamanı</td>
      <td>Bit düzeyinde riskli yorumlama</td>
      <td>Düşük seviyeli sistem kodu</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">typeid</code></td>
      <td>Çalışma zamanı</td>
      <td>Tür bilgisi döndürür</td>
      <td>Gerçek türü karşılaştırma</td>
    </tr>
  </tbody>
</table>

<p><code class="language-plaintext highlighter-rouge">static_cast</code> ile aşağı dönüşüm yapılabilir, fakat nesne hedef türde değilse davranış tanımsız olabilir. Başka bir deyişle hız uğruna emniyet kemerini çıkarmış olursunuz.</p>

<h2 id="tasarım-açısından-son-notlar">Tasarım açısından son notlar</h2>

<p>RTTI kullanışlıdır ancak her nesnenin türünü sürekli sorgulamak tasarım kokusuna dönüşebilir. Çoğu durumda sanal fonksiyonlar daha temiz bir çözüm sunar: nesneye “Sen büyücü müsün?” diye sormak yerine doğrudan <code class="language-plaintext highlighter-rouge">eylemYap()</code> çağrısı yapılabilir.</p>

<p>Yine de eklenti sistemleri, nesne editörleri ve heterojen koleksiyonlar gibi alanlarda RTTI oldukça değerlidir. Kural basittir: Tür gerçekten belirsizse <code class="language-plaintext highlighter-rouge">dynamic_cast</code>, davranış polimorfik biçimde ifade edilebiliyorsa sanal fonksiyon kullanın. Böylece C++ nesneleri maskelerini çıkarsa bile programınız şaşırmaz.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="c++" /><category term="rtti" /><category term="dynamic-cast" /><category term="typeid" /><category term="tür-dönüşümü" /><category term="nesne-yönelimli-programlama" /><summary type="html"><![CDATA[C++ dünyasında bir nesne her zaman göründüğü şey olmayabilir. Elinizde Karakter* türünde bir işaretçi bulunurken, işaret edilen gerçek nesne bir Buyucu veya Savasci olabilir. Çalışma Zamanı Tür Bilgisi, yani RTTI (Run-Time Type Information), program çalışırken bu gerçek kimliği öğrenmemizi ve kalıtım hiyerarşilerinde güvenli dönüşümler yapmamızı sağlar.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/c-rtti-ve-63.png" /><media:content medium="image" url="https://program.sonsuz.us/img/c-rtti-ve-63.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">C++ Sanal Fonksiyonlar ve Çok Biçimlilik: Tek Arayüz, Farklı Davranışlar</title><link href="https://program.sonsuz.us/posts/c-sanal-fonksiyonlar-ve-cok-bicimlilik-tek-arayuz-farkli-davranislar/" rel="alternate" type="text/html" title="C++ Sanal Fonksiyonlar ve Çok Biçimlilik: Tek Arayüz, Farklı Davranışlar" /><published>2026-10-20T00:00:00+00:00</published><updated>2026-10-20T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/c-sanal-fonksiyonlar-ve-cok-bicimlilik-tek-arayuz-farkli-davranislar</id><content type="html" xml:base="https://program.sonsuz.us/posts/c-sanal-fonksiyonlar-ve-cok-bicimlilik-tek-arayuz-farkli-davranislar/"><![CDATA[<p>Bir oyun geliştirdiğimizi ve ekranda savaşçı, büyücü, okçu gibi farklı karakterlerin bulunduğunu düşünelim. Her karakter saldırır, ancak saldırma biçimleri birbirinden farklıdır. C++ çok biçimliliği, bu nesneleri tek bir ortak arayüz üzerinden yönetirken doğru davranışın çalışma zamanında seçilmesini sağlar. Böylece uzun <code class="language-plaintext highlighter-rouge">if-else</code> zincirleri yerine genişletilebilir ve bakımı kolay bir tasarım elde ederiz.</p>

<p><img src="/img/c-sanal-fonksiyonlar-84.svg" alt="c-sanal-fonksiyonlar-84" /></p>

<p>``</p>

<h2 id="çok-biçimlilik-nedir">Çok biçimlilik nedir?</h2>

<p>Polymorphism, kelime anlamıyla <strong>çok biçimlilik</strong> demektir. Nesne yönelimli programlamada aynı fonksiyon çağrısının nesnenin gerçek tipine göre farklı sonuç üretmesini ifade eder. C++ içerisinde bunun iki temel çeşidi vardır:</p>

<table>
  <thead>
    <tr>
      <th>Tür</th>
      <th>Seçim zamanı</th>
      <th>Örnek</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Statik çok biçimlilik</td>
      <td>Derleme zamanı</td>
      <td>Fonksiyon aşırı yükleme, şablonlar</td>
    </tr>
    <tr>
      <td>Dinamik çok biçimlilik</td>
      <td>Çalışma zamanı</td>
      <td>Sanal fonksiyonlar ve kalıtım</td>
    </tr>
  </tbody>
</table>

<p>Dinamik çok biçimlilik için genellikle üç bileşen gerekir: bir temel sınıf, bu sınıftan türeyen sınıflar ve <code class="language-plaintext highlighter-rouge">virtual</code> olarak tanımlanmış bir üye fonksiyon.</p>

<p>Matematiksel olarak ortak bir arayüzü $I$, farklı nesne tiplerini ise $T_1, T_2, \ldots, T_n$ ile gösterelim. Aynı işlem $f$, nesnenin dinamik tipine göre farklı uygulanır:</p>

\[f(I) \rightarrow f_{T_i}(T_i)\]

<p>Yani kod <code class="language-plaintext highlighter-rouge">f</code> işlemini ortak arayüz üzerinden ister; hangi özel uygulamanın çalışacağına program çalışma zamanında karar verir.</p>

<h2 id="sanal-fonksiyon-nasıl-çalışır">Sanal fonksiyon nasıl çalışır?</h2>

<p>Aşağıdaki örnekte bütün karakterler <code class="language-plaintext highlighter-rouge">saldir()</code> arayüzünü sunar, fakat her biri kendine özgü davranı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;memory&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;vector&gt;</span><span class="cp">
</span>
<span class="k">class</span> <span class="nc">Karakter</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="k">virtual</span> <span class="kt">void</span> <span class="n">saldir</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">"Karakter saldırdı.</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="k">virtual</span> <span class="o">~</span><span class="n">Karakter</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">class</span> <span class="nc">Savasci</span> <span class="o">:</span> <span class="k">public</span> <span class="n">Karakter</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="kt">void</span> <span class="n">saldir</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="s">"Savaşçı kılıcını savurdu!</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">Buyucu</span> <span class="o">:</span> <span class="k">public</span> <span class="n">Karakter</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="kt">void</span> <span class="n">saldir</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="s">"Büyücü ateş topu gönderdi!</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">virtual</code> anahtar sözcüğü, çağrılacak fonksiyonun nesnenin gerçek tipine bakılarak seçilmesini sağlar. <code class="language-plaintext highlighter-rouge">override</code> ise türetilmiş sınıftaki fonksiyonun gerçekten bir sanal fonksiyonu ezdiğini derleyiciye doğrulatır. İmza yanlış yazılırsa derleyici hata verir; bu nedenle <code class="language-plaintext highlighter-rouge">override</code> kullanmak iyi bir güvenlik kemeridir.</p>

<p>Derleyiciler bu mekanizmayı çoğunlukla <strong>vtable</strong> adlı sanal fonksiyon tablosu ve nesnede tutulan gizli bir <strong>vptr</strong> işaretçisiyle gerçekleştirir. C++ standardı bu yöntemi zorunlu kılmaz, fakat yaygın uygulama budur. Sanal çağrının küçük bir dolaylı erişim maliyeti vardır; buna karşılık sağladığı esneklik çoğu uygulamada çok daha değerlidir.</p>

<h2 id="nesneleri-ortak-koleksiyonda-yönetmek">Nesneleri ortak koleksiyonda yönetmek</h2>

<p>Akıllı işaretçiler sayesinde farklı karakterleri aynı koleksiyonda güvenli biçimde saklayabiliriz:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">main</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="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">Karakter</span><span class="o">&gt;&gt;</span> <span class="n">takim</span><span class="p">;</span>

    <span class="n">takim</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">Savasci</span><span class="o">&gt;</span><span class="p">());</span>
    <span class="n">takim</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">Buyucu</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">karakter</span> <span class="o">:</span> <span class="n">takim</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">karakter</span><span class="o">-&gt;</span><span class="n">saldir</span><span class="p">();</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Döngü yalnızca <code class="language-plaintext highlighter-rouge">Karakter</code> arayüzünü bilir. Buna rağmen ilk nesne kılıç kullanır, ikincisi ateş topu fırlatır. İşte dinamik çok biçimliliğin küçük ama etkileyici sihri budur.</p>

<h2 id="kritik-ayrıntılar">Kritik ayrıntılar</h2>

<p>Temel sınıf üzerinden silme yapılacaksa yıkıcı mutlaka sanal olmalıdır. Aksi hâlde türetilmiş sınıfın yıkıcısı çağrılmayabilir ve kaynak sızıntıları oluşabilir. Bu nedenle <code class="language-plaintext highlighter-rouge">virtual ~Karakter() = default;</code> önemli bir satırdır.</p>

<p>Nesneleri değer olarak kopyalamak da <strong>object slicing</strong> problemine yol açar:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Savasci</span> <span class="n">savasci</span><span class="p">;</span>
<span class="n">Karakter</span> <span class="n">kopya</span> <span class="o">=</span> <span class="n">savasci</span><span class="p">;</span> <span class="c1">// Savasci kısmı kesilir</span>
<span class="n">kopya</span><span class="p">.</span><span class="n">saldir</span><span class="p">();</span>           <span class="c1">// Temel sınıf davranışı çalışır</span>
</code></pre></div></div>

<p>Dinamik davranışı korumak için temel sınıf referansı, işaretçisi veya <code class="language-plaintext highlighter-rouge">std::unique_ptr</code> gibi akıllı işaretçiler kullanılmalıdır.</p>

<p>Sonuç olarak sanal fonksiyonlar, kodu somut sınıflara değil ortak sözleşmelere bağlar. Yeni bir <code class="language-plaintext highlighter-rouge">Okcu</code> sınıfı eklediğimizde mevcut döngüyü değiştirmemiz gerekmez. Böylece C++ programı hem yeni karakterlere hem de gelecekte gelecek sürpriz gereksinimlere hazırlıklı olur.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="c++" /><category term="polymorphism" /><category term="sanal fonksiyonlar" /><category term="nesne yönelimli programlama" /><category term="kalıtım" /><category term="oop" /><summary type="html"><![CDATA[Bir oyun geliştirdiğimizi ve ekranda savaşçı, büyücü, okçu gibi farklı karakterlerin bulunduğunu düşünelim. Her karakter saldırır, ancak saldırma biçimleri birbirinden farklıdır. C++ çok biçimliliği, bu nesneleri tek bir ortak arayüz üzerinden yönetirken doğru davranışın çalışma zamanında seçilmesini sağlar. Böylece uzun if-else zincirleri yerine genişletilebilir ve bakımı kolay bir tasarım elde ederiz.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/c-sanal-fonksiyonlar-84.png" /><media:content medium="image" url="https://program.sonsuz.us/img/c-sanal-fonksiyonlar-84.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">C++ STL’de Iterator Geçersizliği: erase Tuzağından Güvenle Kaçış</title><link href="https://program.sonsuz.us/posts/c-stlde-iterator-gecersizligi-erase-tuzagindan-guvenle-kacis/" rel="alternate" type="text/html" title="C++ STL’de Iterator Geçersizliği: erase Tuzağından Güvenle Kaçış" /><published>2026-10-20T00:00:00+00:00</published><updated>2026-10-20T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/c-stlde-iterator-gecersizligi-erase-tuzagindan-guvenle-kacis</id><content type="html" xml:base="https://program.sonsuz.us/posts/c-stlde-iterator-gecersizligi-erase-tuzagindan-guvenle-kacis/"><![CDATA[<p>Bir STL konteynerinde dolaşırken eleman silmek, ilk bakışta son derece masum görünür. Ancak yanlış kullanılan tek bir <code class="language-plaintext highlighter-rouge">erase</code>, yineleyiciyi geçersiz hâle getirerek tanımsız davranışa, atlanan elemanlara veya yalnızca cuma akşamları ortaya çıkan gizemli çökmelere neden olabilir. Bu tuzağın kaynağı, her konteynerin elemanlarını bellekte farklı biçimde saklamasıdır.</p>

<p>``</p>

<h2 id="iterator-neden-geçersiz-olur">Iterator neden geçersiz olur?</h2>

<p>Iterator, çoğu zaman bir elemana ulaşmayı sağlayan adres benzeri bir nesnedir. Bir eleman silindiğinde konteyner, belleğini yeniden düzenleyebilir. Iterator artık yaşayan bir elemana işaret etmiyorsa onu karşılaştırmak, artırmak veya dereference etmek güvenli değildir.</p>

<p>Örneğin <code class="language-plaintext highlighter-rouge">vector</code>, elemanlarını ardışık bellekte tutar. İndisi $i$ olan eleman silindiğinde arkasındaki yaklaşık</p>

\[n-i-1\]

<p>eleman sola taşınır. Böylece silinen elemanı ve sonrasını gösteren iterator’lar geçersizleşir. İşlemin zaman karmaşıklığı da bu taşıma nedeniyle genel olarak $O(n)$ olur.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><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">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">};</span>
<span class="k">auto</span> <span class="n">it</span> <span class="o">=</span> <span class="n">sayilar</span><span class="p">.</span><span class="n">begin</span><span class="p">()</span> <span class="o">+</span> <span class="mi">2</span><span class="p">;</span> <span class="c1">// 3</span>

<span class="n">sayilar</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">it</span><span class="p">);</span>
<span class="c1">// it artık geçersizdir!</span>
<span class="c1">// std::cout &lt;&lt; *it; // Tanımsız davranış</span>
</code></pre></div></div>

<p>Buradaki yaygın yanılgı, <code class="language-plaintext highlighter-rouge">it</code> değişkeninin otomatik olarak sıradaki elemana geçeceğini düşünmektir. Oysa <code class="language-plaintext highlighter-rouge">erase</code>, eski iterator’ı onarmaz; bunun yerine geçerli olan sonraki iterator’ı döndürür.</p>

<h2 id="güvenli-silme-deseni">Güvenli silme deseni</h2>

<p>Dolaşma sırasında silme yapılacaksa <code class="language-plaintext highlighter-rouge">erase</code> dönüş değeri kullanılmalıdır:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><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">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">};</span>

<span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">it</span> <span class="o">=</span> <span class="n">sayilar</span><span class="p">.</span><span class="n">begin</span><span class="p">();</span> <span class="n">it</span> <span class="o">!=</span> <span class="n">sayilar</span><span class="p">.</span><span class="n">end</span><span class="p">();</span> <span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="n">it</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">it</span> <span class="o">=</span> <span class="n">sayilar</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">it</span><span class="p">);</span> <span class="c1">// Sonraki geçerli konumu al</span>
    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
        <span class="o">++</span><span class="n">it</span><span class="p">;</span>                   <span class="c1">// Yalnızca silinmediyse ilerle</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Döngünün üçüncü bölümü özellikle boş bırakılmıştır. Hem <code class="language-plaintext highlighter-rouge">erase</code> sonrasında hem de döngü sonunda <code class="language-plaintext highlighter-rouge">++it</code> çalıştırılsaydı bir eleman atlanabilirdi.</p>

<h2 id="konteynerlere-göre-kurallar">Konteynerlere göre kurallar</h2>

<table>
  <thead>
    <tr>
      <th>Konteyner</th>
      <th>Silme sonrası genel iterator durumu</th>
      <th style="text-align: right">Silme maliyeti</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">vector</code></td>
      <td>Silinen ve sonrasındaki iterator’lar geçersiz</td>
      <td style="text-align: right">$O(n)$</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">deque</code></td>
      <td>Ortadan silmede çoğunlukla tüm iterator’lar geçersiz</td>
      <td style="text-align: right">$O(n)$</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">list</code>, <code class="language-plaintext highlighter-rouge">forward_list</code></td>
      <td>Yalnızca silinen elemana ait iterator geçersiz</td>
      <td style="text-align: right">$O(1)$</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">map</code>, <code class="language-plaintext highlighter-rouge">set</code></td>
      <td>Yalnızca silinen elemana ait iterator geçersiz</td>
      <td style="text-align: right">$O(\log n)$</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">unordered_map</code>, <code class="language-plaintext highlighter-rouge">unordered_set</code></td>
      <td>Genellikle yalnızca silinen elemana ait iterator geçersiz</td>
      <td style="text-align: right">Ortalama $O(1)$</td>
    </tr>
  </tbody>
</table>

<p><img src="/img/c-stlde-iterator-54.svg" alt="c-stlde-iterator-54" /></p>

<p><code class="language-plaintext highlighter-rouge">list</code> düğüm tabanlı olduğu için bir düğümün çıkarılması diğer düğümlerin adreslerini değiştirmez. <code class="language-plaintext highlighter-rouge">map</code> ve <code class="language-plaintext highlighter-rouge">set</code> gibi ağaç tabanlı yapılarda da benzer bir güvence vardır. Buna rağmen silinen iterator’ın kendisini kullanmak her durumda hatadır.</p>

<p><code class="language-plaintext highlighter-rouge">deque</code> daha dikkatli ele alınmalıdır: Baştan veya sondan silmenin kuralları daha sınırlı etkiler doğurabilirken ortadan silme, iterator’ları geniş ölçüde geçersizleştirir. Kodun taşınabilir ve anlaşılır olması için daima <code class="language-plaintext highlighter-rouge">erase</code> dönüş değerini kullanmak en güvenli yaklaşımdır.</p>

<h2 id="modern-c-ile-erase_if">Modern C++ ile erase_if</h2>

<p>Amaç yalnızca koşula uyan elemanları temizlemekse C++20, iterator yönetimini gizleyen daha okunaklı bir araç sunar:</p>

<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;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="kt">int</span><span class="o">&gt;</span> <span class="n">sayilar</span><span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">};</span>

<span class="n">std</span><span class="o">::</span><span class="n">erase_if</span><span class="p">(</span><span class="n">sayilar</span><span class="p">,</span> <span class="p">[](</span><span class="kt">int</span> <span class="n">deger</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="n">deger</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">});</span>
</code></pre></div></div>

<p>Eski standartlarda <code class="language-plaintext highlighter-rouge">vector</code> için erase-remove deyimi kullanılır:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">sayilar</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span>
    <span class="n">std</span><span class="o">::</span><span class="n">remove_if</span><span class="p">(</span><span class="n">sayilar</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">sayilar</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span>
                   <span class="p">[](</span><span class="kt">int</span> <span class="n">x</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">x</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span><span class="p">;</span> <span class="p">}),</span>
    <span class="n">sayilar</span><span class="p">.</span><span class="n">end</span><span class="p">()</span>
<span class="p">);</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">remove_if</code> fiziksel silme yapmaz; korunacak elemanları öne taşır ve mantıksal yeni sonu döndürür. Asıl küçültmeyi <code class="language-plaintext highlighter-rouge">erase</code> gerçekleştirir.</p>

<p>Kısa kural şudur: Bir silme işleminden sonra eski iterator’ın hâlâ geçerli olduğunu varsayma. Konteynerin geçersizleştirme kurallarını kontrol et, mümkünse <code class="language-plaintext highlighter-rouge">erase</code> tarafından döndürülen iterator’ı kullan ve toplu koşullu silmelerde <code class="language-plaintext highlighter-rouge">std::erase_if</code> tercih et. Böylece iterator’ların hayaletlere dönüşmesini engellersin.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="c++" /><category term="stl" /><category term="iterator" /><category term="konteynerler" /><category term="erase" /><category term="bellek" /><summary type="html"><![CDATA[Bir STL konteynerinde dolaşırken eleman silmek, ilk bakışta son derece masum görünür. Ancak yanlış kullanılan tek bir erase, yineleyiciyi geçersiz hâle getirerek tanımsız davranışa, atlanan elemanlara veya yalnızca cuma akşamları ortaya çıkan gizemli çökmelere neden olabilir. Bu tuzağın kaynağı, her konteynerin elemanlarını bellekte farklı biçimde saklamasıdır.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/c-stlde-iterator-54.png" /><media:content medium="image" url="https://program.sonsuz.us/img/c-stlde-iterator-54.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">C++ Template Tür Çıkarımı: Beklenmedik Instantiation Hatalarını Anlamak</title><link href="https://program.sonsuz.us/posts/c-template-tur-cikarimi-beklenmedik-instantiation-hatalarini-anlamak/" rel="alternate" type="text/html" title="C++ Template Tür Çıkarımı: Beklenmedik Instantiation Hatalarını Anlamak" /><published>2026-10-20T00:00:00+00:00</published><updated>2026-10-20T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/c-template-tur-cikarimi-beklenmedik-instantiation-hatalarini-anlamak</id><content type="html" xml:base="https://program.sonsuz.us/posts/c-template-tur-cikarimi-beklenmedik-instantiation-hatalarini-anlamak/"><![CDATA[<p>C++ şablonları, aynı algoritmayı farklı türlerle kullanmayı sağlayan güçlü bir mekanizmadır. Fakat derleyicinin bir türü başarıyla çıkarması, ilgili şablonun sorunsuz biçimde üretileceği anlamına gelmez. Bazen masum görünen bir fonksiyon çağrısı, derleyiciyi henüz hazır olmayan bir gövdeyi örneklemeye zorlar ve ekranı uzun, hiyeroglif benzeri hata mesajlarıyla doldurur.
``</p>

<h2 id="tür-çıkarımı-ile-örnekleme-aynı-şey-değildir">Tür çıkarımı ile örnekleme aynı şey değildir</h2>

<p>Bir fonksiyon şablonu çağrıldığında süreç kabaca üç aşamadan geçer:</p>

<ol>
  <li><strong>Tür çıkarımı:</strong> Şablon parametreleri, fonksiyon argümanlarından belirlenir.</li>
  <li><strong>Yerine koyma:</strong> Çıkarılan türler bildirimdeki ilgili konumlara yazılır.</li>
  <li><strong>Örnekleme:</strong> Gerekli fonksiyon veya sınıf gövdesi gerçek türlerle üretilir.</li>
</ol>

<p>Bunu basitleştirilmiş biçimde şöyle gösterebiliriz:</p>

\[\text{çağrı} \rightarrow \text{deduction} \rightarrow \text{substitution} \rightarrow \text{instantiation}\]

<p>Sorun, hatanın hangi aşamada oluştuğuna bağlıdır. Yerine koyma sırasında oluşan bazı hatalar SFINAE veya constraint mekanizmasıyla adayın elenmesini sağlar. Şablon gövdesinin örneklenmesi sırasında oluşan hata ise çoğunlukla doğrudan derleme hatasıdır.</p>

<table>
  <thead>
    <tr>
      <th>Durum</th>
      <th>Hatanın oluştuğu yer</th>
      <th>Tipik sonuç</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Parametre veya dönüş türü</td>
      <td>Immediate context</td>
      <td>SFINAE ile aday elenebilir</td>
    </tr>
    <tr>
      <td>Fonksiyon gövdesi</td>
      <td>Instantiation</td>
      <td>Sert derleme hatası</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">requires</code> ifadesi</td>
      <td>Constraint kontrolü</td>
      <td>Kısıt sağlanmaz</td>
    </tr>
    <tr>
      <td>Seçilmeyen <code class="language-plaintext highlighter-rouge">if constexpr</code> dalı</td>
      <td>Örneklenmez</td>
      <td>Hata genellikle oluşmaz</td>
    </tr>
  </tbody>
</table>

<h2 id="auto-dönüş-türünün-hazırladığı-sürpriz"><code class="language-plaintext highlighter-rouge">auto</code> dönüş türünün hazırladığı sürpriz</h2>

<p>Aşağıdaki kod, bir türün <code class="language-plaintext highlighter-rouge">foo()</code> fonksiyonuna sahip olup olmadığını kontrol ediyor gibi görünür:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;concepts&gt;</span><span class="cp">
</span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span>
<span class="k">auto</span> <span class="nf">probe</span><span class="p">(</span><span class="n">T</span> <span class="n">value</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="n">value</span><span class="p">.</span><span class="n">foo</span><span class="p">();</span>
<span class="p">}</span>

<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span>
<span class="k">concept</span> <span class="n">HasFoo</span> <span class="o">=</span> <span class="k">requires</span><span class="p">(</span><span class="n">T</span> <span class="n">value</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">probe</span><span class="p">(</span><span class="n">value</span><span class="p">);</span>
<span class="p">};</span>

<span class="k">static_assert</span><span class="p">(</span><span class="o">!</span><span class="n">HasFoo</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">);</span>
</code></pre></div></div>

<p>Fakat <code class="language-plaintext highlighter-rouge">probe&lt;int&gt;</code> fonksiyonunun dönüş türünü bulabilmek için derleyici gövdeyi örneklemek zorundadır. <code class="language-plaintext highlighter-rouge">int</code> üzerinde <code class="language-plaintext highlighter-rouge">foo()</code> bulunmadığından hata, güvenli bir constraint başarısızlığı yerine fonksiyon gövdesinde patlayabilir. Derleyici adeta “Sadece bakacaktım, bütün evi inşa ettim” der.</p>

<p>Kontrol edilmesini istediğimiz ifadeyi dönüş türüne taşıyarak hatayı uygun bağlama alabiliriz:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span>
<span class="k">auto</span> <span class="nf">probe</span><span class="p">(</span><span class="n">T</span> <span class="n">value</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="k">decltype</span><span class="p">(</span><span class="n">value</span><span class="p">.</span><span class="n">foo</span><span class="p">())</span> <span class="p">{</span>
    <span class="k">return</span> <span class="n">value</span><span class="p">.</span><span class="n">foo</span><span class="p">();</span>
<span class="p">}</span>

<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span>
<span class="k">concept</span> <span class="n">HasFoo</span> <span class="o">=</span> <span class="k">requires</span><span class="p">(</span><span class="n">T</span> <span class="n">value</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">probe</span><span class="p">(</span><span class="n">value</span><span class="p">);</span>
<span class="p">};</span>
</code></pre></div></div>

<p>Artık <code class="language-plaintext highlighter-rouge">decltype(value.foo())</code>, fonksiyon bildirimindeki immediate context içinde değerlendirilir. İfade geçersizse aday kullanılabilir sayılmaz; gereksiz gövde örneklemesi yapılmaz.</p>

<h2 id="tembel-olmayan-tür-seçimi">Tembel olmayan tür seçimi</h2>

<p><code class="language-plaintext highlighter-rouge">std::conditional_t</code> de sık rastlanan bir tuzaktır. Koşul yalnızca bir dalı seçse bile iki tür argümanının da önce geçerli olması gerekir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;type_traits&gt;</span><span class="cp">
</span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span>
<span class="k">using</span> <span class="n">ValueOrSelf</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">conditional_t</span><span class="o">&lt;</span>
    <span class="k">requires</span> <span class="p">{</span> <span class="k">typename</span> <span class="n">T</span><span class="o">::</span><span class="n">value_type</span><span class="p">;</span> <span class="p">},</span>
    <span class="k">typename</span> <span class="n">T</span><span class="o">::</span><span class="n">value_type</span><span class="p">,</span>
    <span class="n">T</span>
<span class="o">&gt;</span><span class="p">;</span>

<span class="c1">// ValueOrSelf&lt;int&gt; x; // int::value_type geçersizdir</span>
</code></pre></div></div>

<p>Burada koşul <code class="language-plaintext highlighter-rouge">false</code> olsa bile <code class="language-plaintext highlighter-rouge">typename T::value_type</code> oluşturulmaya çalışılır. Çözüm, seçimi uzmanlaşmalarla tembel hâle getirmektir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">,</span> <span class="k">class</span> <span class="o">=</span> <span class="kt">void</span><span class="p">&gt;</span>
<span class="k">struct</span> <span class="nc">value_or_self</span> <span class="p">{</span>
    <span class="k">using</span> <span class="n">type</span> <span class="o">=</span> <span class="n">T</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span>
<span class="k">struct</span> <span class="nc">value_or_self</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">void_t</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">::</span><span class="n">value_type</span><span class="o">&gt;&gt;</span> <span class="p">{</span>
    <span class="k">using</span> <span class="n">type</span> <span class="o">=</span> <span class="k">typename</span> <span class="n">T</span><span class="o">::</span><span class="n">value_type</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span>
<span class="k">using</span> <span class="n">value_or_self_t</span> <span class="o">=</span> <span class="k">typename</span> <span class="n">value_or_self</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;::</span><span class="n">type</span><span class="p">;</span>
</code></pre></div></div>

<h2 id="hataları-kontrol-altında-tutmak">Hataları kontrol altında tutmak</h2>

<p>Şablon kodunda şu alışkanlıklar hata mesajlarını ciddi ölçüde iyileştirir:</p>

<ul>
  <li>Gereksinimleri fonksiyon gövdesi yerine <code class="language-plaintext highlighter-rouge">requires</code>, <code class="language-plaintext highlighter-rouge">concept</code> veya <code class="language-plaintext highlighter-rouge">decltype</code> ile bildirimde ifade edin.</li>
  <li>Seçilmeyecek kodu <code class="language-plaintext highlighter-rouge">if constexpr</code> içinde tutun.</li>
  <li>Tür seçiminin gerçekten tembel olup olmadığını sorgulayın.</li>
  <li>Şablonları yalnızca geçerli türlerle değil, özellikle geçersiz türlerle de test edin.</li>
  <li>Derleyicinin hata izinde ilk kullanıcı kodunu bulun; standart kütüphane satırlarında kaybolmayın.</li>
</ul>

<p>Kısacası tür çıkarımı yalnızca doğru anahtarı bulur; instantiation ise kapının arkasındaki odanın gerçekten var olup olmadığını kontrol eder. Sağlam template tasarımı, bu kontrolü mümkün olduğunca erken ve kontrollü yapmaktır.</p>

<p><img src="/img/c-template-tur-33.svg" alt="c-template-tur-33" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="c++" /><category term="template" /><category term="tür çıkarımı" /><category term="instantiation" /><category term="sfinae" /><category term="concepts" /><summary type="html"><![CDATA[C++ şablonları, aynı algoritmayı farklı türlerle kullanmayı sağlayan güçlü bir mekanizmadır. Fakat derleyicinin bir türü başarıyla çıkarması, ilgili şablonun sorunsuz biçimde üretileceği anlamına gelmez. Bazen masum görünen bir fonksiyon çağrısı, derleyiciyi henüz hazır olmayan bir gövdeyi örneklemeye zorlar ve ekranı uzun, hiyeroglif benzeri hata mesajlarıyla doldurur.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/c-template-tur-33.png" /><media:content medium="image" url="https://program.sonsuz.us/img/c-template-tur-33.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">C++’ta İstisna Fırlatan Kurucular ve Yarım Kalan Nesnelerde Kaynak Sızıntısı</title><link href="https://program.sonsuz.us/posts/cta-istisna-firlatan-kurucular-ve-yarim-kalan-nesnelerde-kaynak-sizintisi/" rel="alternate" type="text/html" title="C++’ta İstisna Fırlatan Kurucular ve Yarım Kalan Nesnelerde Kaynak Sızıntısı" /><published>2026-10-20T00:00:00+00:00</published><updated>2026-10-20T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/cta-istisna-firlatan-kurucular-ve-yarim-kalan-nesnelerde-kaynak-sizintisi</id><content type="html" xml:base="https://program.sonsuz.us/posts/cta-istisna-firlatan-kurucular-ve-yarim-kalan-nesnelerde-kaynak-sizintisi/"><![CDATA[<p>Bir C++ kurucusu çalışırken istisna fırlatırsa nesne hiçbir zaman tamamen oluşmuş sayılmaz. Bu nedenle nesnenin kendi yıkıcısı çağrılmaz. Kurucu içinde elle edinilmiş bellek, dosya veya kilit gibi kaynaklar varsa bu davranış kolayca sızıntıya dönüşebilir. Neyse ki C++’ın üye yıkım kuralları ve RAII yaklaşımı, doğru kullanıldığında yarım kalan inşaatı güvenli biçimde temizler.</p>

<p>``</p>

<h2 id="nesne-neden-yarım-kalır">Nesne neden “yarım” kalır?</h2>

<p>Bir nesnenin yaşam süresi, kurucusu başarıyla tamamlandığında başlar. Kurucu istisna ile sonlanırsa dışarıdan kullanılabilecek geçerli bir nesne yoktur. Dolayısıyla aşağıdaki yıkıcı çalıştırılmaz:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">RiskliTampon</span> <span class="p">{</span>
    <span class="kt">int</span><span class="o">*</span> <span class="n">veri_</span><span class="p">;</span>

<span class="nl">public:</span>
    <span class="k">explicit</span> <span class="n">RiskliTampon</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">adet</span><span class="p">)</span>
        <span class="o">:</span> <span class="n">veri_</span><span class="p">(</span><span class="k">new</span> <span class="kt">int</span><span class="p">[</span><span class="n">adet</span><span class="p">])</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">adet</span> <span class="o">&gt;</span> <span class="mi">1000</span><span class="p">)</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">"Tampon çok büyük"</span><span class="p">);</span>
        <span class="p">}</span>
    <span class="p">}</span>

    <span class="o">~</span><span class="n">RiskliTampon</span><span class="p">()</span> <span class="p">{</span>
        <span class="k">delete</span><span class="p">[]</span> <span class="n">veri_</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">new int[adet]</code> başarılı olduktan sonra istisna fırlatılırsa <code class="language-plaintext highlighter-rouge">~RiskliTampon()</code> çağrılmaz. Sonuç olarak <code class="language-plaintext highlighter-rouge">veri_</code> tarafından gösterilen dizi serbest bırakılamaz. Ham işaretçi üyesinin yok edilmesi yalnızca işaretçi değerini ortadan kaldırır; gösterdiği belleğe <code class="language-plaintext highlighter-rouge">delete[]</code> uygulamaz.</p>

<p>Basit bir risk modeli şu şekilde düşünülebilir:</p>

\[R = P(E) \times K\]

<p>Burada $P(E)$ kurucunun kaynak edinildikten sonra istisna fırlatma olasılığı, $K$ ise temizlenmeden kalan kaynağın maliyetidir. Dosya tanıtıcısı veya mutex gibi sınırlı kaynaklarda $K$, birkaç baytlık bellekten çok daha yüksek olabilir.</p>

<h2 id="hangi-parçalar-otomatik-temizlenir">Hangi parçalar otomatik temizlenir?</h2>

<p>C++ önemli bir güvence sağlar: Kurucu başarısız olduğunda, yapımı başarıyla tamamlanmış taban sınıflar ve üye nesneler ters sırada yok edilir. Henüz kurulmamış üyeler içinse yıkıcı çağrılmaz.</p>

<table>
  <thead>
    <tr>
      <th>Kaynak türü</th>
      <th>Kurucu başarısız olunca</th>
      <th>Sızıntı riski</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Ham işaretçiyle alınan bellek</td>
      <td>Otomatik <code class="language-plaintext highlighter-rouge">delete</code> yapılmaz</td>
      <td>Yüksek</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">std::unique_ptr</code></td>
      <td>Üye yıkıcısı belleği bırakır</td>
      <td>Düşük</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">std::vector</code></td>
      <td>İç belleğini otomatik temizler</td>
      <td>Düşük</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">std::ofstream</code></td>
      <td>Dosyayı kapatır</td>
      <td>Düşük</td>
    </tr>
    <tr>
      <td>Elle kilitlenen mutex</td>
      <td>Açık kalabilir</td>
      <td>Yüksek</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">std::lock_guard</code></td>
      <td>Kilidi otomatik bırakır</td>
      <td>Düşük</td>
    </tr>
  </tbody>
</table>

<p><img src="/img/cta-istisna-firlatan-51.svg" alt="cta-istisna-firlatan-51" /></p>

<p>İşte RAII’nin özü budur: Kaynağın ömrünü bir nesnenin ömrüne bağlamak. “Resource Acquisition Is Initialization” adı biraz uzun, yaptığı iş ise oldukça pratiktir: Temizlik kodunu unutulamaz hâle getirir.</p>

<h2 id="güvenli-çözüm-kaynakları-üyelere-emanet-etmek">Güvenli çözüm: Kaynakları üyelere emanet etmek</h2>

<p>Riskli sınıf <code class="language-plaintext highlighter-rouge">std::vector</code> kullanılarak şöyle düzeltilebilir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">GuvenliTampon</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">veri_</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="n">ofstream</span> <span class="n">gunluk_</span><span class="p">;</span>

<span class="nl">public:</span>
    <span class="k">explicit</span> <span class="n">GuvenliTampon</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">adet</span><span class="p">)</span>
        <span class="o">:</span> <span class="n">veri_</span><span class="p">(</span><span class="n">adet</span><span class="p">),</span> <span class="n">gunluk_</span><span class="p">(</span><span class="s">"tampon.log"</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">gunluk_</span><span class="p">)</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">"Günlük açılamadı"</span><span class="p">);</span>
        <span class="p">}</span>

        <span class="k">if</span> <span class="p">(</span><span class="n">adet</span> <span class="o">&gt;</span> <span class="mi">1000</span><span class="p">)</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">"Tampon çok büyük"</span><span class="p">);</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<p>İstisna ikinci kontrolda fırlatılsa bile <code class="language-plaintext highlighter-rouge">gunluk_</code> dosyayı kapatır, ardından <code class="language-plaintext highlighter-rouge">veri_</code> belleğini bırakır. Sınıfa özel bir yıkıcı yazmak bile gerekmez. Bu yaklaşım aynı zamanda <strong>Rule of Zero</strong> ilkesine uyar: Kaynak yöneten standart sınıfları kullan, kopyalama, taşıma ve yıkım ayrıntılarını derleyiciye bırak.</p>

<p>Dinamik ve tekil bir nesne gerekiyorsa <code class="language-plaintext highlighter-rouge">std::unique_ptr</code> tercih edilebilir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">MotorYoneticisi</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">Motor</span><span class="o">&gt;</span> <span class="n">motor_</span><span class="p">;</span>

<span class="nl">public:</span>
    <span class="n">MotorYoneticisi</span><span class="p">()</span>
        <span class="o">:</span> <span class="n">motor_</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">Motor</span><span class="o">&gt;</span><span class="p">())</span> <span class="p">{</span>
        <span class="n">ayarlariYukle</span><span class="p">();</span> <span class="c1">// Fırlatsa bile Motor yok edilir.</span>
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<p>Kurucu gövdesindeki <code class="language-plaintext highlighter-rouge">try/catch</code> ile elle temizlik yapmak mümkündür; ancak birden fazla çıkış yolu olduğunda kırılgandır. Kurucuya ait function-try-block da genellikle istisnayı kaydetmek veya başka türe çevirmek içindir; RAII’nin yerini almamalıdır.</p>

<p>Pratik kural nettir: Kurucuda <code class="language-plaintext highlighter-rouge">new</code>, <code class="language-plaintext highlighter-rouge">fopen</code>, <code class="language-plaintext highlighter-rouge">lock</code> veya benzeri çıplak kaynak edinimleri görüyorsanız alarm zilleri çalsın. Kaynağı hemen <code class="language-plaintext highlighter-rouge">std::vector</code>, <code class="language-plaintext highlighter-rouge">std::unique_ptr</code>, dosya akışı ya da kilit koruyucusu gibi bir RAII nesnesine teslim edin. Böylece nesne yarım kalsa bile temizlik tam olur.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="c++" /><category term="istisna yönetimi" /><category term="raii" /><category term="kurucu" /><category term="kaynak yönetimi" /><category term="akıllı işaretçiler" /><summary type="html"><![CDATA[Bir C++ kurucusu çalışırken istisna fırlatırsa nesne hiçbir zaman tamamen oluşmuş sayılmaz. Bu nedenle nesnenin kendi yıkıcısı çağrılmaz. Kurucu içinde elle edinilmiş bellek, dosya veya kilit gibi kaynaklar varsa bu davranış kolayca sızıntıya dönüşebilir. Neyse ki C++’ın üye yıkım kuralları ve RAII yaklaşımı, doğru kullanıldığında yarım kalan inşaatı güvenli biçimde temizler.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/cta-istisna-firlatan-51.png" /><media:content medium="image" url="https://program.sonsuz.us/img/cta-istisna-firlatan-51.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">C++’ta Sanal Fonksiyonlar ve Varsayılan Parametreler: İki Farklı Karar Mekanizması</title><link href="https://program.sonsuz.us/posts/cta-sanal-fonksiyonlar-ve-varsayilan-parametreler-iki-farkli-karar-mekanizmasi/" rel="alternate" type="text/html" title="C++’ta Sanal Fonksiyonlar ve Varsayılan Parametreler: İki Farklı Karar Mekanizması" /><published>2026-10-20T00:00:00+00:00</published><updated>2026-10-20T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/cta-sanal-fonksiyonlar-ve-varsayilan-parametreler-iki-farkli-karar-mekanizmasi</id><content type="html" xml:base="https://program.sonsuz.us/posts/cta-sanal-fonksiyonlar-ve-varsayilan-parametreler-iki-farkli-karar-mekanizmasi/"><![CDATA[<p>C++’ta sanal fonksiyonlar çalışma zamanlı polimorfizmin yıldızıdır; varsayılan parametreler ise çağrıları kısaltan kullanışlı yardımcılardır. Ancak bu iki özellik aynı fonksiyonda buluştuğunda küçük bir sürpriz ortaya çıkar: Çalıştırılan fonksiyon türetilmiş sınıfa aitken kullanılan varsayılan değer temel sınıftan gelebilir. İlk bakışta çelişkili görünse de sebep, C++ derleyicisinin iki kararı farklı zamanlarda vermesidir.</p>

<p>``</p>

<h2 id="problemi-bir-örnekle-görelim">Problemi Bir Örnekle Görelim</h2>

<p>Aşağıdaki programda hem temel hem de türetilmiş sınıf aynı sanal fonksiyon için farklı varsayılan değerler tanımlıyor:</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">
</span>
<span class="k">class</span> <span class="nc">Base</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="k">virtual</span> <span class="kt">void</span> <span class="n">yazdir</span><span class="p">(</span><span class="kt">int</span> <span class="n">adet</span> <span class="o">=</span> <span class="mi">1</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">"Base: "</span> <span class="o">&lt;&lt;</span> <span class="n">adet</span> <span class="o">&lt;&lt;</span> <span class="sc">'\n'</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="k">virtual</span> <span class="o">~</span><span class="n">Base</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">class</span> <span class="nc">Derived</span> <span class="o">:</span> <span class="k">public</span> <span class="n">Base</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="kt">void</span> <span class="n">yazdir</span><span class="p">(</span><span class="kt">int</span> <span class="n">adet</span> <span class="o">=</span> <span class="mi">5</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="s">"Derived: "</span> <span class="o">&lt;&lt;</span> <span class="n">adet</span> <span class="o">&lt;&lt;</span> <span class="sc">'\n'</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">Derived</span> <span class="n">nesne</span><span class="p">;</span>
    <span class="n">Base</span><span class="o">*</span> <span class="n">ptr</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">nesne</span><span class="p">;</span>

    <span class="n">ptr</span><span class="o">-&gt;</span><span class="n">yazdir</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Pek çok geliştirici çıktının <code class="language-plaintext highlighter-rouge">Derived: 5</code> olmasını bekler. Gerçek çıktı ise şöyledir:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Derived: 1
</code></pre></div></div>

<p>Burada <code class="language-plaintext highlighter-rouge">Derived::yazdir</code> çalıştırılmış, fakat <code class="language-plaintext highlighter-rouge">Base::yazdir</code> bildirimindeki <code class="language-plaintext highlighter-rouge">1</code> değeri kullanılmıştır. C++ bize adeta “Fonksiyonu dinamik, parametreyi statik seçtim!” demektedir.</p>

<h2 id="statik-ve-dinamik-bağlama">Statik ve Dinamik Bağlama</h2>

<p>Sanal fonksiyonun hangi gövdesinin çalışacağı, nesnenin gerçek çalışma zamanı türüne göre belirlenir. <code class="language-plaintext highlighter-rouge">ptr</code>, <code class="language-plaintext highlighter-rouge">Base*</code> türünde olmasına rağmen bir <code class="language-plaintext highlighter-rouge">Derived</code> nesnesini gösterdiği için sanal çağrı <code class="language-plaintext highlighter-rouge">Derived::yazdir</code> fonksiyonuna yönlendirilir.</p>

<p>Varsayılan parametreler ise polimorfik değildir. Derleyici, eksik argümanı çağrı noktasında ve ifadenin statik türüne bakarak doğrudan ekler. Kavramsal olarak şu dönüşüm yapılır:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">ptr</span><span class="o">-&gt;</span><span class="n">yazdir</span><span class="p">();</span>

<span class="c1">// Derleyicinin çağrı noktasındaki yaklaşımı:</span>
<span class="n">ptr</span><span class="o">-&gt;</span><span class="n">yazdir</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
</code></pre></div></div>

<p>Ardından sanal çağrı mekanizması hangi fonksiyon gövdesinin çalışacağını seçer. Süreci basitçe şöyle ifade edebiliriz:</p>

\[Çağrı = VarsayılanDeğer(StatikTür) + FonksiyonGövdesi(DinamikTür)\]

<table>
  <thead>
    <tr>
      <th>Karar</th>
      <th>Kullanılan tür</th>
      <th>Belirlenme zamanı</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Varsayılan argüman</td>
      <td>Statik tür (<code class="language-plaintext highlighter-rouge">Base*</code>)</td>
      <td>Derleme zamanı</td>
    </tr>
    <tr>
      <td>Fonksiyon gövdesi</td>
      <td>Dinamik tür (<code class="language-plaintext highlighter-rouge">Derived</code>)</td>
      <td>Çalışma zamanı</td>
    </tr>
    <tr>
      <td>Sonuç</td>
      <td><code class="language-plaintext highlighter-rouge">Derived::yazdir(1)</code></td>
      <td>İki mekanizmanın birleşimi</td>
    </tr>
  </tbody>
</table>

<p><img src="/img/cta-sanal-fonksiyonlar-41.svg" alt="cta-sanal-fonksiyonlar-41" /></p>

<p>Aynı nesneyi doğrudan çağırırsak sonuç değişir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">nesne</span><span class="p">.</span><span class="n">yazdir</span><span class="p">();</span> <span class="c1">// Derived::yazdir(5)</span>
<span class="n">ptr</span><span class="o">-&gt;</span><span class="n">yazdir</span><span class="p">();</span>  <span class="c1">// Derived::yazdir(1)</span>
</code></pre></div></div>

<p>Çünkü ilk ifadenin statik türü <code class="language-plaintext highlighter-rouge">Derived</code>, ikincisininki <code class="language-plaintext highlighter-rouge">Base*</code> üzerinden <code class="language-plaintext highlighter-rouge">Base</code> sınıfıdır.</p>

<h2 id="neden-böyle-tasarlanmıştır">Neden Böyle Tasarlanmıştır?</h2>

<p>Varsayılan argüman, fonksiyonun çalışma zamanı davranışının değil, bildirimin sunduğu arayüzün parçasıdır. Derleyici çağrı noktasını işlerken nesnenin gelecekte hangi gerçek türe sahip olacağını bilmek zorunda değildir. Ayrıca varsayılan değerlerin sanal tabloya eklenmesi daha karmaşık bir çağrı modeli ve ek çalışma zamanı maliyeti oluştururdu.</p>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Sanal fonksiyon</th>
      <th>Varsayılan parametre</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Polimorfik mi?</td>
      <td>Evet</td>
      <td>Hayır</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">override</code> ile denetlenir mi?</td>
      <td>Evet</td>
      <td>Hayır</td>
    </tr>
    <tr>
      <td>Dinamik türe bakar mı?</td>
      <td>Evet</td>
      <td>Hayır</td>
    </tr>
    <tr>
      <td>Alt sınıfta değiştirmek güvenli mi?</td>
      <td>Davranış için evet</td>
      <td>Genellikle hayır</td>
    </tr>
  </tbody>
</table>

<h2 id="güvenli-tasarım-yaklaşımı">Güvenli Tasarım Yaklaşımı</h2>

<p>En temiz çözüm, varsayılan değeri yalnızca sanal olmayan bir arayüz fonksiyonunda tutmaktır:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Base</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="kt">void</span> <span class="n">yazdir</span><span class="p">(</span><span class="kt">int</span> <span class="n">adet</span> <span class="o">=</span> <span class="mi">1</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span>
        <span class="n">yazdirImpl</span><span class="p">(</span><span class="n">adet</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="k">virtual</span> <span class="o">~</span><span class="n">Base</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>

<span class="k">private</span><span class="o">:</span>
    <span class="k">virtual</span> <span class="kt">void</span> <span class="n">yazdirImpl</span><span class="p">(</span><span class="kt">int</span> <span class="n">adet</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">"Base: "</span> <span class="o">&lt;&lt;</span> <span class="n">adet</span> <span class="o">&lt;&lt;</span> <span class="sc">'\n'</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">};</span>

<span class="k">class</span> <span class="nc">Derived</span> <span class="o">:</span> <span class="k">public</span> <span class="n">Base</span> <span class="p">{</span>
<span class="nl">private:</span>
    <span class="kt">void</span> <span class="n">yazdirImpl</span><span class="p">(</span><span class="kt">int</span> <span class="n">adet</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="s">"Derived: "</span> <span class="o">&lt;&lt;</span> <span class="n">adet</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>Bu yaklaşımda varsayılan değer tek yerde tanımlanır, sanal uygulama ise yalnızca davranışı değiştirir. Böylece işaretçinin statik türüne bağlı sürprizler ortadan kalkar. Kısa kural şudur: Sanal fonksiyonlarda farklı varsayılan parametreler tanımlamayın; varsayılan seçimini arayüze, polimorfik davranışı ayrı bir sanal fonksiyona bırakın.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="c++" /><category term="oop" /><category term="sanal-fonksiyonlar" /><category term="varsayılan-parametreler" /><category term="polimorfizm" /><summary type="html"><![CDATA[C++’ta sanal fonksiyonlar çalışma zamanlı polimorfizmin yıldızıdır; varsayılan parametreler ise çağrıları kısaltan kullanışlı yardımcılardır. Ancak bu iki özellik aynı fonksiyonda buluştuğunda küçük bir sürpriz ortaya çıkar: Çalıştırılan fonksiyon türetilmiş sınıfa aitken kullanılan varsayılan değer temel sınıftan gelebilir. İlk bakışta çelişkili görünse de sebep, C++ derleyicisinin iki kararı farklı zamanlarda vermesidir.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/cta-sanal-fonksiyonlar-41.png" /><media:content medium="image" url="https://program.sonsuz.us/img/cta-sanal-fonksiyonlar-41.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">grep, sed ve awk: Metin İşlerken Doğru Aleti Seçme Rehberi</title><link href="https://program.sonsuz.us/posts/grep-sed-ve-awk-metin-islerken-dogru-aleti-secme-rehberi/" rel="alternate" type="text/html" title="grep, sed ve awk: Metin İşlerken Doğru Aleti Seçme Rehberi" /><published>2026-10-20T00:00:00+00:00</published><updated>2026-10-20T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/grep-sed-ve-awk-metin-islerken-dogru-aleti-secme-rehberi</id><content type="html" xml:base="https://program.sonsuz.us/posts/grep-sed-ve-awk-metin-islerken-dogru-aleti-secme-rehberi/"><![CDATA[<p>Komut satırında her metin problemi bir çivi gibi görünüyorsa, elimizdeki ilk komutu çekiç olarak kullanmak cazip gelir. Böylece <code class="language-plaintext highlighter-rouge">grep</code> ile hesap yapmaya, <code class="language-plaintext highlighter-rouge">sed</code> ile sütun toplamaya veya <code class="language-plaintext highlighter-rouge">awk</code> ile yalnızca bir kelime aramaya çalışırız. Sonuç bazen çalışır; fakat okunabilirlik, taşınabilirlik ve bakım kolaylığı sessizce pencereden kaçar.</p>

<p><img src="/img/grep-sed-ve-18.svg" alt="grep-sed-ve-18" /></p>

<p>``</p>
<h2 id="üç-aracın-temel-zihinsel-modeli">Üç aracın temel zihinsel modeli</h2>

<p>Bu araçların hepsi standart girdiyi okuyabilir ve boru hatlarında kullanılabilir; ancak metne farklı gözlüklerle bakarlar.</p>

<ul>
  <li><strong>grep</strong>, satırların belirli bir desene uyup uymadığıyla ilgilenir.</li>
  <li><strong>sed</strong>, metni satır satır dönüştüren bir akış düzenleyicisidir.</li>
  <li><strong>awk</strong>, kayıtları alanlara ayırıp koşul, değişken ve aritmetik kullanabilen küçük bir programlama dilidir.</li>
</ul>

<p>Bir dosyada $n$ satır, her satırda ortalama $m$ karakter varsa basit tarama maliyeti kabaca $O(nm)$ olur. Araç seçiminin asıl farkı çoğunlukla teorik karmaşıklık değil, aynı işi ifade etmek için gereken zihinsel ve sözdizimsel karmaşıklıktır.</p>

<table>
  <thead>
    <tr>
      <th>Görev</th>
      <th>Doğru başlangıç aracı</th>
      <th>Temel güç</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Eşleşen satırları bulmak</td>
      <td><code class="language-plaintext highlighter-rouge">grep</code></td>
      <td>Düzenli ifadeyle filtreleme</td>
    </tr>
    <tr>
      <td>Metni değiştirmek veya silmek</td>
      <td><code class="language-plaintext highlighter-rouge">sed</code></td>
      <td>Akış üzerinde dönüşüm</td>
    </tr>
    <tr>
      <td>Sütunları işlemek ve hesaplamak</td>
      <td><code class="language-plaintext highlighter-rouge">awk</code></td>
      <td>Alanlar, koşullar ve aritmetik</td>
    </tr>
  </tbody>
</table>

<h2 id="grep-ile-tornavida-kullanmak">grep ile tornavida kullanmak</h2>

<p><code class="language-plaintext highlighter-rouge">grep</code> yalnızca eşleşen satırları seçmek için mükemmeldir:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">grep</span> <span class="nt">-i</span> <span class="s2">"error"</span> app.log
</code></pre></div></div>

<p>Bu komut, büyük-küçük harfi önemsemeden <code class="language-plaintext highlighter-rouge">error</code> içeren satırları getirir. Fakat ikinci sütundaki değerleri toplamak istiyorsak <code class="language-plaintext highlighter-rouge">grep</code>, görevi tek başına doğal biçimde ifade edemez. Karmaşık <code class="language-plaintext highlighter-rouge">grep</code>, <code class="language-plaintext highlighter-rouge">cut</code>, <code class="language-plaintext highlighter-rouge">paste</code> ve <code class="language-plaintext highlighter-rouge">bc</code> zincirleri kurulabilir; ancak bu, market alışverişine forkliftle gitmeye benzer.</p>

<p>Doğal çözüm <code class="language-plaintext highlighter-rouge">awk</code> kullanmaktır:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">awk</span> <span class="s1">'{ toplam += $2 } END { print toplam }'</span> satis.txt
</code></pre></div></div>

<p>Burada her satır bir kayıt, boşluklarla ayrılmış parçalar ise alan kabul edilir. <code class="language-plaintext highlighter-rouge">$2</code> ikinci alanı, <code class="language-plaintext highlighter-rouge">END</code> ise bütün kayıtlar işlendikten sonraki aşamayı temsil eder.</p>

<h2 id="sed-ile-muhasebe-yapmaya-çalışmak">sed ile muhasebe yapmaya çalışmak</h2>

<p><code class="language-plaintext highlighter-rouge">sed</code>, değiştirme işlemlerinde parlar:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sed</span> <span class="s1">'s/http:/https:/g'</span> adresler.txt
</code></pre></div></div>

<p>Komut, her satırdaki tüm <code class="language-plaintext highlighter-rouge">http:</code> ifadelerini <code class="language-plaintext highlighter-rouge">https:</code> ile değiştirir. Buna karşılık sayısal karşılaştırma, toplam veya ortalama gerektiğinde <code class="language-plaintext highlighter-rouge">sed</code> komutları hızla anlaşılmaz hâle gelir.</p>

<p>Örneğin üçüncü sütunu 100’den büyük kayıtları seçmek için doğru yaklaşım şudur:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">awk</span> <span class="s1">'$3 &gt; 100 { print $1, $3 }'</span> veriler.txt
</code></pre></div></div>

<p>Ortalama hesaplamak da doğrudandır. Değerlerin toplamı $S$, kayıt sayısı $N$ ise ortalama</p>

\[\bar{x} = \frac{S}{N}\]

<p>olur:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">awk</span> <span class="s1">'{ s += $3; n++ } END { if (n) print s / n }'</span> veriler.txt
</code></pre></div></div>

<h2 id="awk-ile-basit-aramayı-büyütmek">awk ile basit aramayı büyütmek</h2>

<p><code class="language-plaintext highlighter-rouge">awk '/hata/' app.log</code> geçerli bir komuttur; fakat yalnızca eşleşen satırları istiyorsak niyetimizi <code class="language-plaintext highlighter-rouge">grep 'hata' app.log</code> daha açık anlatır. <code class="language-plaintext highlighter-rouge">awk</code>, alan seçimi veya ek mantık devreye girdiğinde anlam kazanır:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">awk</span> <span class="s1">'$2 == "ERROR" &amp;&amp; $4 &gt;= 500 { print $1, $4 }'</span> app.log
</code></pre></div></div>

<p>Bu örnek hem alan karşılaştırır hem sayısal koşul uygular. Yani <code class="language-plaintext highlighter-rouge">awk</code> burada gerçekten maaşını hak eder.</p>

<h2 id="araçlar-rakip-değil-ekip-arkadaşıdır">Araçlar rakip değil, ekip arkadaşıdır</h2>

<p>Tek bir komuta bütün işi yüklemek zorunda değiliz. Önce ilgili satırları filtreleyip sonra metni dönüştürebiliriz:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">grep</span> <span class="s1">'^WARN'</span> app.log | <span class="nb">sed</span> <span class="s1">'s/^WARN/UYARI/'</span>
</code></pre></div></div>

<p>Yine de gereksiz süreçlerden kaçınmak gerekir. Aynı işlem tek ve anlaşılır bir <code class="language-plaintext highlighter-rouge">awk</code> programıyla yapılabiliyorsa uzun boru hattı kurmak hata ayıklamayı zorlaştırabilir.</p>

<p>Pratik karar kuralı basittir: <strong>Buluyorsan grep, değiştiriyorsan sed, alanlar üzerinde düşünüyor veya hesaplıyorsan awk.</strong> Görev büyüdükçe kabuk komutlarını zorlamak yerine Python gibi genel amaçlı bir dile geçmek de yenilgi değil, doğru mühendislik kararıdır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="shell" /><category term="grep" /><category term="sed" /><category term="awk" /><category term="linux" /><category term="metin işleme" /><summary type="html"><![CDATA[Komut satırında her metin problemi bir çivi gibi görünüyorsa, elimizdeki ilk komutu çekiç olarak kullanmak cazip gelir. Böylece grep ile hesap yapmaya, sed ile sütun toplamaya veya awk ile yalnızca bir kelime aramaya çalışırız. Sonuç bazen çalışır; fakat okunabilirlik, taşınabilirlik ve bakım kolaylığı sessizce pencereden kaçar.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/grep-sed-ve-18.png" /><media:content medium="image" url="https://program.sonsuz.us/img/grep-sed-ve-18.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>