<?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-20T18:05:59+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# 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++ 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><entry><title type="html">Java İstisna Yönetimi: try, catch ve finally ile Güvenli Kod</title><link href="https://program.sonsuz.us/posts/java-istisna-yonetimi-try-catch-ve-finally-ile-guvenli-kod/" rel="alternate" type="text/html" title="Java İstisna Yönetimi: try, catch ve finally ile Güvenli Kod" /><published>2026-10-20T00:00:00+00:00</published><updated>2026-10-20T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/java-istisna-yonetimi-try-catch-ve-finally-ile-guvenli-kod</id><content type="html" xml:base="https://program.sonsuz.us/posts/java-istisna-yonetimi-try-catch-ve-finally-ile-guvenli-kod/"><![CDATA[<p>Bir uygulamada her şey planlandığı gibi gitmez: Dosya bulunamaz, kullanıcı sayı yerine metin girer veya ağ bağlantısı aniden kesilir. Java istisna yönetimi, bu beklenmeyen durumları kontrollü biçimde karşılayarak programın dramatik bir şekilde sahneden düşmesini engeller. Amaç hataları gizlemek değil; onları anlamlı, izlenebilir ve güvenli bir akış içinde yönetmektir.
``</p>
<h2 id="i̇stisna-nedir">İstisna nedir?</h2>

<p>İstisna, programın normal çalışma akışını bozan bir olaydır. Java’da istisnalar nesne olarak temsil edilir ve temel olarak <code class="language-plaintext highlighter-rouge">Throwable</code> sınıfından türetilir. Bir sorun oluştuğunda istisna “fırlatılır”; uygun bir yönetici bulunduğunda ise “yakalanır”.</p>

<p>Bu davranışı basitçe şöyle düşünebiliriz:</p>

\[\text{Güvenli Akış} = \text{Riskli İşlem} + \text{Hata Yakalama} + \text{Temizlik}\]

<p>Java’daki hata hiyerarşisinin iki önemli kolu vardır:</p>

<table>
  <thead>
    <tr>
      <th>Tür</th>
      <th>Açıklama</th>
      <th>Örnek</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Checked exception</td>
      <td>Derleyicinin yönetilmesini zorunlu tuttuğu istisnalardır</td>
      <td><code class="language-plaintext highlighter-rouge">IOException</code>, <code class="language-plaintext highlighter-rouge">SQLException</code></td>
    </tr>
    <tr>
      <td>Unchecked exception</td>
      <td>Genellikle programlama hatalarından doğar</td>
      <td><code class="language-plaintext highlighter-rouge">NullPointerException</code>, <code class="language-plaintext highlighter-rouge">ArithmeticException</code></td>
    </tr>
    <tr>
      <td>Error</td>
      <td>Uygulamanın çoğunlukla düzeltemeyeceği ciddi JVM sorunlarıdır</td>
      <td><code class="language-plaintext highlighter-rouge">OutOfMemoryError</code></td>
    </tr>
  </tbody>
</table>

<p><img src="/img/java-istisna-yonetimi-75.svg" alt="java-istisna-yonetimi-75" /></p>

<h2 id="try-ve-catch-nasıl-çalışır">try ve catch nasıl çalışır?</h2>

<p>Risk oluşturabilecek kod <code class="language-plaintext highlighter-rouge">try</code> bloğuna yazılır. Bir istisna meydana gelirse Java, ilgili türü karşılayan <code class="language-plaintext highlighter-rouge">catch</code> bloğunu arar. Böylece uygulama tamamen sonlanmak yerine alternatif bir davranış gösterebilir.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">BolmeOrnegi</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
        <span class="kt">int</span> <span class="n">bolunen</span> <span class="o">=</span> <span class="mi">24</span><span class="o">;</span>
        <span class="kt">int</span> <span class="n">bolen</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span>

        <span class="k">try</span> <span class="o">{</span>
            <span class="kt">int</span> <span class="n">sonuc</span> <span class="o">=</span> <span class="n">bolunen</span> <span class="o">/</span> <span class="n">bolen</span><span class="o">;</span>
            <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Sonuç: "</span> <span class="o">+</span> <span class="n">sonuc</span><span class="o">);</span>
        <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">ArithmeticException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
            <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Bir sayı sıfıra bölünemez."</span><span class="o">);</span>
            <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Teknik ayrıntı: "</span> <span class="o">+</span> <span class="n">e</span><span class="o">.</span><span class="na">getMessage</span><span class="o">());</span>
        <span class="o">}</span>

        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Program çalışmaya devam ediyor."</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Burada sıfıra bölme işlemi <code class="language-plaintext highlighter-rouge">ArithmeticException</code> üretir. <code class="language-plaintext highlighter-rouge">catch</code> bloğu hatayı yakalar, kullanıcıya anlaşılır bir mesaj verir ve programın sonraki satırlara devam etmesini sağlar.</p>

<p>Birden fazla hata türü için birden fazla <code class="language-plaintext highlighter-rouge">catch</code> kullanılabilir. Ancak özel istisnalar önce, daha genel olanlar sonra yazılmalıdır. Aksi hâlde genel blok diğerlerini erişilemez yapabilir.</p>

<h2 id="finally-neden-kullanılır">finally neden kullanılır?</h2>

<p><code class="language-plaintext highlighter-rouge">finally</code> bloğu, istisna oluşsa da oluşmasa da çalıştırılması gereken işlemler içindir. Dosya kapatmak, bağlantıyı sonlandırmak veya geçici kaynakları temizlemek klasik kullanım örnekleridir.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">try</span> <span class="o">{</span>
    <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Veritabanı işlemi başlatıldı."</span><span class="o">);</span>
    <span class="c1">// Riskli sorgular burada çalıştırılır.</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">RuntimeException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
    <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"İşlem başarısız: "</span> <span class="o">+</span> <span class="n">e</span><span class="o">.</span><span class="na">getMessage</span><span class="o">());</span>
<span class="o">}</span> <span class="k">finally</span> <span class="o">{</span>
    <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Bağlantı ve kaynaklar temizleniyor."</span><span class="o">);</span>
<span class="o">}</span>
</code></pre></div></div>

<table>
  <thead>
    <tr>
      <th>Blok</th>
      <th>Ne zaman çalışır?</th>
      <th>Temel görevi</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">try</code></td>
      <td>Her zaman ilk olarak</td>
      <td>Riskli kodu çalıştırmak</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">catch</code></td>
      <td>Eşleşen istisna oluşursa</td>
      <td>Hatayı kontrollü biçimde ele almak</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">finally</code></td>
      <td>Normalde her durumda</td>
      <td>Kaynakları temizlemek</td>
    </tr>
  </tbody>
</table>

<p>Modern Java’da dosya ve benzeri <code class="language-plaintext highlighter-rouge">AutoCloseable</code> kaynaklar için <code class="language-plaintext highlighter-rouge">try-with-resources</code> daha güvenlidir:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">try</span> <span class="o">(</span><span class="kt">var</span> <span class="n">okuyucu</span> <span class="o">=</span> <span class="k">new</span> <span class="n">java</span><span class="o">.</span><span class="na">io</span><span class="o">.</span><span class="na">BufferedReader</span><span class="o">(</span>
        <span class="k">new</span> <span class="n">java</span><span class="o">.</span><span class="na">io</span><span class="o">.</span><span class="na">FileReader</span><span class="o">(</span><span class="s">"veriler.txt"</span><span class="o">)))</span> <span class="o">{</span>
    <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">okuyucu</span><span class="o">.</span><span class="na">readLine</span><span class="o">());</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">java</span><span class="o">.</span><span class="na">io</span><span class="o">.</span><span class="na">IOException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
    <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Dosya okunamadı: "</span> <span class="o">+</span> <span class="n">e</span><span class="o">.</span><span class="na">getMessage</span><span class="o">());</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Bu yapı, okuyucuyu otomatik kapatır ve unutulan kaynaklar yüzünden oluşabilecek sızıntıları azaltır.</p>

<h2 id="sağlam-istisna-yönetimi-için-ipuçları">Sağlam istisna yönetimi için ipuçları</h2>

<ul>
  <li>Boş bir <code class="language-plaintext highlighter-rouge">catch</code> bloğu kullanarak hatayı sessizce yutmayın.</li>
  <li>Kullanıcıya anlaşılır, geliştiriciye ayrıntılı günlük mesajları sağlayın.</li>
  <li>Yalnızca gerçekten yönetebileceğiniz istisnaları yakalayın.</li>
  <li><code class="language-plaintext highlighter-rouge">Exception</code> gibi aşırı genel türleri gereksiz yere kullanmayın.</li>
  <li>İstisnaları normal karar mekanizması yerine koymayın.</li>
</ul>

<p>İyi tasarlanmış istisna yönetimi, uygulamanın hiç hata vermemesi anlamına gelmez. Asıl başarı; hata geldiğinde paniklemeyen, kaynaklarını temizleyen, kullanıcıyı bilgilendiren ve mümkünse güvenli biçimde yoluna devam eden bir sistem kurmaktır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="java" /><category term="exception" /><category term="hata-yönetimi" /><category term="try-catch" /><category term="finally" /><category term="programlama" /><summary type="html"><![CDATA[Bir uygulamada her şey planlandığı gibi gitmez: Dosya bulunamaz, kullanıcı sayı yerine metin girer veya ağ bağlantısı aniden kesilir. Java istisna yönetimi, bu beklenmeyen durumları kontrollü biçimde karşılayarak programın dramatik bir şekilde sahneden düşmesini engeller. Amaç hataları gizlemek değil; onları anlamlı, izlenebilir ve güvenli bir akış içinde yönetmektir.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/java-istisna-yonetimi-75.png" /><media:content medium="image" url="https://program.sonsuz.us/img/java-istisna-yonetimi-75.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Python’da `is` ve `==`: Küçük Tam Sayı Önbelleğinin Kurduğu Tuzak</title><link href="https://program.sonsuz.us/posts/pythonda-is-ve-kucuk-tam-sayi-onbelleginin-kurdugu-tuzak/" rel="alternate" type="text/html" title="Python’da `is` ve `==`: Küçük Tam Sayı Önbelleğinin Kurduğu Tuzak" /><published>2026-10-20T00:00:00+00:00</published><updated>2026-10-20T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/pythonda-is-ve-kucuk-tam-sayi-onbelleginin-kurdugu-tuzak</id><content type="html" xml:base="https://program.sonsuz.us/posts/pythonda-is-ve-kucuk-tam-sayi-onbelleginin-kurdugu-tuzak/"><![CDATA[<p><img src="/img/pythonda-is-ve-17.svg" alt="pythonda-is-ve-17" /></p>

<p>Python öğrenirken <code class="language-plaintext highlighter-rouge">is</code> ve <code class="language-plaintext highlighter-rouge">==</code> bazen aynı sonucu veriyormuş gibi görünür. Özellikle küçük tam sayılarla yapılan denemelerde iki operatörün de <code class="language-plaintext highlighter-rouge">True</code> döndürmesi, aralarında gerçek bir fark olmadığı yanılgısını doğurabilir. Oysa biri değerleri, diğeri nesnelerin kimliğini karşılaştırır; küçük tam sayı önbelleklemesi ise bu farkı geçici olarak gizleyen küçük bir illüzyondur.</p>

<p>``</p>

<h2 id="eşitlik-ve-kimlik-aynı-şey-değildir">Eşitlik ve kimlik aynı şey değildir</h2>

<p><code class="language-plaintext highlighter-rouge">==</code> operatörü iki nesnenin <strong>değer bakımından eşit</strong> olup olmadığını denetler. Bu işlem çoğunlukla nesnenin <code class="language-plaintext highlighter-rouge">__eq__</code> metodu üzerinden gerçekleştirilir. <code class="language-plaintext highlighter-rouge">is</code> ise iki değişkenin bellekteki <strong>aynı nesneye referans verip vermediğine</strong> bakar ve özelleştirilemez.</p>

<table>
  <thead>
    <tr>
      <th>Operatör</th>
      <th>Sorduğu soru</th>
      <th>Temel mekanizma</th>
      <th>Tipik kullanım</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">==</code></td>
      <td>Değerler eşit mi?</td>
      <td><code class="language-plaintext highlighter-rouge">__eq__</code></td>
      <td>Sayı, metin ve koleksiyon karşılaştırma</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">is</code></td>
      <td>Aynı nesne mi?</td>
      <td>Nesne kimliği</td>
      <td><code class="language-plaintext highlighter-rouge">None</code>, sentinel ve tekil nesneler</td>
    </tr>
  </tbody>
</table>

<p>Tam sayılar açısından ilişkiyi kabaca şöyle gösterebiliriz:</p>

\[a \text{ is } b \Rightarrow a == b\]

<p>Ancak ters yön garanti değildir:</p>

\[a == b \not\Rightarrow a \text{ is } b\]

<p>Yani aynı değere sahip iki farklı nesne bulunabilir. İki ayrı kâğıda <code class="language-plaintext highlighter-rouge">1000</code> yazılması, kâğıtları aynı kâğıt yapmaz.</p>

<h2 id="küçük-tam-sayı-önbelleği">Küçük tam sayı önbelleği</h2>

<p>Yaygın Python uygulaması CPython, sık kullanılan küçük tam sayı nesnelerini tekrar tekrar üretmemek için önceden hazır tutar. Tipik olarak $-5$ ile $256$ arasındaki tam sayılar önbelleğe alınır. Bu sınırlar CPython uygulama ayrıntısıdır; dil tarafından bütün Python uygulamaları için garanti edilmez.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">a</span> <span class="o">=</span> <span class="mi">100</span>
<span class="n">b</span> <span class="o">=</span> <span class="mi">100</span>

<span class="nf">print</span><span class="p">(</span><span class="n">a</span> <span class="o">==</span> <span class="n">b</span><span class="p">)</span>  <span class="c1"># True: değerler eşit
</span><span class="nf">print</span><span class="p">(</span><span class="n">a</span> <span class="ow">is</span> <span class="n">b</span><span class="p">)</span>  <span class="c1"># CPython'da çoğunlukla True: aynı önbellek nesnesi
</span></code></pre></div></div>

<p>Burada <code class="language-plaintext highlighter-rouge">is</code> sonucunun <code class="language-plaintext highlighter-rouge">True</code> olması, sayısal karşılaştırma için doğru operatörü kullandığımız anlamına gelmez. Yalnızca <code class="language-plaintext highlighter-rouge">a</code> ve <code class="language-plaintext highlighter-rouge">b</code>, CPython tarafından paylaşılmış aynı <code class="language-plaintext highlighter-rouge">100</code> nesnesine bağlanmıştır.</p>

<p>Daha büyük değerlerde maske düşebilir:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">a</span> <span class="o">=</span> <span class="nf">int</span><span class="p">(</span><span class="sh">"</span><span class="s">1000</span><span class="sh">"</span><span class="p">)</span>
<span class="n">b</span> <span class="o">=</span> <span class="nf">int</span><span class="p">(</span><span class="sh">"</span><span class="s">1000</span><span class="sh">"</span><span class="p">)</span>

<span class="nf">print</span><span class="p">(</span><span class="n">a</span> <span class="o">==</span> <span class="n">b</span><span class="p">)</span>  <span class="c1"># True
</span><span class="nf">print</span><span class="p">(</span><span class="n">a</span> <span class="ow">is</span> <span class="n">b</span><span class="p">)</span>  <span class="c1"># Genellikle False
</span><span class="nf">print</span><span class="p">(</span><span class="nf">id</span><span class="p">(</span><span class="n">a</span><span class="p">),</span> <span class="nf">id</span><span class="p">(</span><span class="n">b</span><span class="p">))</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">int</code> çağrıları çalışma anında eşit değerli fakat ayrı nesneler oluşturabilir. <code class="language-plaintext highlighter-rouge">id()</code> çıktılarının farklı olması, değişkenlerin aynı nesneyi göstermediğini açıklar.</p>

<h2 id="neden-bazı-testler-yine-şaşırtır">Neden bazı testler yine şaşırtır?</h2>

<p>Aynı kod bloğunda yazılan sabitler, derleyici optimizasyonları nedeniyle paylaşılabilir. Metinlerde interning, sabit katlama ve etkileşimli kabuğun çalışma biçimi de sonuçları etkileyebilir. Bu nedenle <code class="language-plaintext highlighter-rouge">257 is 257</code> benzeri deneyler farklı Python sürümlerinde, REPL’de veya bir dosya içinde farklı davranabilir. Ayrıca modern Python sürümleri, bir literal ile <code class="language-plaintext highlighter-rouge">is</code> kullanılınca <code class="language-plaintext highlighter-rouge">SyntaxWarning</code> gösterebilir.</p>

<table>
  <thead>
    <tr>
      <th>Senaryo</th>
      <th>Doğru tercih</th>
      <th>Neden?</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">puan</code> değeri 100 mü?</td>
      <td><code class="language-plaintext highlighter-rouge">puan == 100</code></td>
      <td>Değer karşılaştırılır</td>
    </tr>
    <tr>
      <td>Sonuç <code class="language-plaintext highlighter-rouge">None</code> mı?</td>
      <td><code class="language-plaintext highlighter-rouge">sonuc is None</code></td>
      <td><code class="language-plaintext highlighter-rouge">None</code> tekil nesnedir</td>
    </tr>
    <tr>
      <td>İki liste aynı içeriğe mi sahip?</td>
      <td><code class="language-plaintext highlighter-rouge">liste1 == liste2</code></td>
      <td>Elemanlar karşılaştırılır</td>
    </tr>
    <tr>
      <td>İki ad aynı listeyi mi gösteriyor?</td>
      <td><code class="language-plaintext highlighter-rouge">liste1 is liste2</code></td>
      <td>Nesne kimliği araştırılır</td>
    </tr>
  </tbody>
</table>

<h2 id="güvenli-kullanım-kuralı">Güvenli kullanım kuralı</h2>

<p>Sayıları, metinleri ve koleksiyon içeriklerini karşılaştırırken <code class="language-plaintext highlighter-rouge">==</code> kullanın. <code class="language-plaintext highlighter-rouge">is</code> operatörünü başta <code class="language-plaintext highlighter-rouge">None</code> olmak üzere kimliği özellikle önemli olan tekil nesnelere ayırın:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">kullaniciyi_bul</span><span class="p">(</span><span class="n">kimlik</span><span class="p">):</span>
    <span class="n">kullanici</span> <span class="o">=</span> <span class="nf">veritabaninda_ara</span><span class="p">(</span><span class="n">kimlik</span><span class="p">)</span>

    <span class="k">if</span> <span class="n">kullanici</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
        <span class="k">return</span> <span class="sh">"</span><span class="s">Kullanıcı bulunamadı</span><span class="sh">"</span>

    <span class="k">if</span> <span class="n">kullanici</span><span class="p">.</span><span class="n">yas</span> <span class="o">==</span> <span class="mi">18</span><span class="p">:</span>
        <span class="k">return</span> <span class="sh">"</span><span class="s">Kullanıcı tam 18 yaşında</span><span class="sh">"</span>

    <span class="k">return</span> <span class="sh">"</span><span class="s">Kullanıcı bulundu</span><span class="sh">"</span>
</code></pre></div></div>

<p>İlk koşul özel <code class="language-plaintext highlighter-rouge">None</code> nesnesinin kimliğini, ikinci koşul ise sayısal değeri denetler. Kısacası önbelleğe güvenerek yazılan <code class="language-plaintext highlighter-rouge">is</code> karşılaştırması tesadüfen çalışabilir; doğru semantiğe dayanan <code class="language-plaintext highlighter-rouge">==</code> ise niyetinizi açık, taşınabilir ve güvenilir biçimde ifade eder.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="python" /><category term="operatörler" /><category term="bellek" /><category term="cpython" /><category term="hata ayıklama" /><category term="nesne kimliği" /><summary type="html"><![CDATA[Python öğrenirken is ve == bazen aynı sonucu veriyormuş gibi görünür. Özellikle küçük tam sayılarla yapılan denemelerde iki operatörün de True döndürmesi, aralarında gerçek bir fark olmadığı yanılgısını doğurabilir. Oysa biri değerleri, diğeri nesnelerin kimliğini karşılaştırır; küçük tam sayı önbelleklemesi ise bu farkı geçici olarak gizleyen küçük bir illüzyondur.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/pythonda-is-ve-17.png" /><media:content medium="image" url="https://program.sonsuz.us/img/pythonda-is-ve-17.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>