C++ PROGRAMLAMA

C++ logosu yanında derleme zinciri kaynak koddan makine koduna akış şeması

Python'da yazdığın satır anında çalışır; C++'ta ise önce derleyiciyle bir pazarlık yaparsın. Bu pazarlık çoğu yeni başlayanı yıldırır — oysa C++'ın bütün gücü tam da orada saklıdır: derleyici, kodun makinede nasıl duracağını satır satır bilmek ister ve karşılığında sana yorumlayıcılı dillerin ulaşamayacağı bir hız ile bellek kontrolü verir. Oyun motorları, finansal işlem sistemleri, otonom araç yazılımları ve işletim sistemlerinin C++ ile yazılmasının nedeni budur.

Bu yazı C++ ile kod yazmanın pratiğine odaklanıyor: derleme modeli nasıl işler, dosyalar nasıl organize edilir, pointer ile referans nerede ayrışır, STL ne sunar, modern C++ eskisinden nasıl farklılaşır. Dilin tarihi veya hangi sektörde kullanıldığı değil — doğrudan kodun kendisi.

Derleme Modeli Nasıl İşler?

C++ kaynak kodu doğrudan çalışmaz; dört aşamalı bir hattan geçerek makine koduna dönüşür. Bu hattı bilmek, hata mesajlarını okumanın ön koşuludur:

  1. Önişlemci (preprocessor): #include ve #define satırlarını işler — metin düzeyinde yapıştırma yapar
  2. Derleme (compile): Her .cpp dosyası bağımsız olarak nesne dosyasına (.o / .obj) çevrilir
  3. Bağlama (link): Nesne dosyaları ve kütüphaneler tek çalıştırılabilir dosyada birleştirilir
  4. Çalıştırma: İşletim sistemi programı yükler — artık derleyici sahnede değildir

En küçük çalışan program üzerinden bakalım:

#include <iostream>

int main() {
    std::cout << "Merhaba Veriakademi" << std::endl;
    return 0;
}

Komut satırında derlemek tek satır: g++ -std=c++20 -Wall main.cpp -o program. Buradaki -Wall bayrağı tüm uyarıları açar — tecrübeli C++ geliştiricileri uyarıları hata gibi okur, çünkü derleyicinin "şüpheliyim" dediği satır genelde gelecekteki bug'dır.

Hata mesajlarının iki ayrı kaynağı olduğunu bilmek saatler kazandırır: "undefined reference" görüyorsan sorun derlemede değil bağlamadadır — bir fonksiyonun gövdesini yazmamışsın ya da kütüphaneyi linker'a vermemişsindir. "expected ;" tarzı mesajlar ise derleme aşamasının işidir.

Header ve Source Ayrımı

C++ projelerinde kod iki dosya tipine bölünür: header (.h / .hpp) bildirimleri taşır, source (.cpp) tanımları. Bu ayrım Java veya C#'tan gelenlere gereksiz görünür ama derleme modelinin doğal sonucudur — her .cpp bağımsız derlendiği için, başka dosyadaki fonksiyonun "imzasını" header üzerinden öğrenir.

// hesap.hpp — bildirim
#pragma once

class HesapMakinesi {
public:
    double topla(double a, double b);
    double yuzdeHesapla(double tutar, double oran);
};
// hesap.cpp — tanım
#include "hesap.hpp"

double HesapMakinesi::topla(double a, double b) {
    return a + b;
}

double HesapMakinesi::yuzdeHesapla(double tutar, double oran) {
    return tutar * oran / 100.0;
}

#pragma once satırı, header'ın aynı derleme birimine iki kez yapıştırılmasını önler. Tipik bir Türk yazılım evi projesinde klasör düzeni şöyle kurulur: include/ altında header'lar, src/ altında source dosyaları, tests/ altında birim testler ve kökte derlemeyi yöneten bir CMakeLists.txt. CMake, platformlar arası derlemenin fiilî standardı hâline gelmiştir.

Değer, Pointer, Referans

C++'ı diğer dillerden ayıran ve öğrenenleri en çok zorlayan üçlü budur. Aynı veriye üç farklı yoldan erişilebilir:

int sayi = 42;

int kopya = sayi;     // DEĞER: bağımsız kopya
int* ptr = &sayi;     // POINTER: adresi tutar, yeniden yönlendirilebilir
int& ref = sayi;      // REFERANS: takma ad, hep aynı değişkene bağlı

*ptr = 50;            // sayi artık 50
ref = 60;             // sayi artık 60
kopya = 99;           // sayi etkilenmez

Pratik kural şudur: varsayılan olarak referans kullan, "hiçbir şeye işaret etmeyebilir" durumu varsa pointer'a geç. Referans null olamaz ve yeniden bağlanamaz — bu kısıt bir eksiklik değil, güvencedir. Fonksiyon parametrelerinde büyük nesneleri kopyalamamak için const referans kalıbı her gün yazılan koddur:

void raporla(const std::vector<double>& satislar) {
    // satislar kopyalanmadı, sadece okunabilir
    double toplam = 0;
    for (double s : satislar) toplam += s;
    std::cout << "Toplam: " << toplam << std::endl;
}
Değer pointer ve referans farkını kutu adres ve takma ad metaforuyla gösteren şema

RAII ve Kaynak Yönetimi

C++'ın çöp toplayıcısı (garbage collector) yoktur — ve modern C++'ta buna rağmen elle delete yazmak kötü koddur. Çelişki gibi görünen bu durumu RAII çözer: Resource Acquisition Is Initialization. Kaynak (bellek, dosya, kilit, soket) bir nesnenin ömrüne bağlanır; nesne scope dışına çıktığında yıkıcısı kaynağı otomatik bırakır.

#include <fstream>
#include <memory>

void islemYap() {
    std::ofstream dosya("log.txt");      // dosya açıldı
    auto musteri = std::make_unique<Musteri>("Ayşe");  // bellek alındı

    dosya << "işlem başladı\n";

    if (hataVarMi()) {
        return;   // erken çıkış: dosya da bellek de OTOMATİK temizlenir
    }
}   // normal çıkış: yine otomatik temizlik

Buradaki std::unique_ptr, modern C++'ın akıllı pointer'larından biridir: sahipliği tek başına taşır, kopyalanamaz, scope bitince belleği bırakır. Paylaşımlı sahiplik gerekiyorsa std::shared_ptr devreye girer. Ham new/delete çifti, bugün ancak çok özel durumlarla sınırlı, düşük seviye kütüphane kodunda görülür.

RAII'nin güzelliği istisnalarla birlikte ortaya çıkar: kod hangi satırdan çıkarsa çıksın — return, exception, normal akış — temizlik garantilidir. Java'daki try-finally ve Python'daki with bloklarının yaptığı işi, C++ tip sisteminin içine gömer.

STL Konteynerleri ve Algoritmalar

Standart Şablon Kütüphanesi (STL), C++'ın hazır veri yapısı ve algoritma deposudur. Günlük işin büyük kısmı dört konteynerle döner:

  • std::vector — dinamik dizi; varsayılan tercih, elemanlar bellekte bitişik durur
  • std::map — sıralı anahtar-değer; dengeli ağaç üstünde, anahtarlar hep sıralı gezilir
  • std::unordered_map — hash tabanlı anahtar-değer; ortalama sabit zamanlı erişim
  • std::string — metin; C'deki char dizilerinin dertlerinden kurtarır

Algoritmalar konteynerlerden bağımsız yazılmıştır ve birlikte kullanıldığında kod hem kısalır hem hızlanır:

#include <vector>
#include <algorithm>

std::vector<int> puanlar = {72, 45, 88, 91, 63};

std::sort(puanlar.begin(), puanlar.end());

int gecenler = std::count_if(puanlar.begin(), puanlar.end(),
                             [](int p) { return p >= 60; });

auto enYuksek = std::max_element(puanlar.begin(), puanlar.end());

Köşeli parantezle başlayan [](int p) { ... } ifadesi bir lambda — isimsiz, yerinde tanımlanan fonksiyon. C++11 ile gelen lambda'lar, STL algoritmalarını günlük kullanılabilir hâle getiren özelliktir.

Modern C++ Alışkanlıkları

Dil, 2011'den beri üç yılda bir güncelleniyor: C++11, 14, 17, 20 derken C++23 yayımlandı ve komite C++26 üzerinde çalışıyor. "Modern C++" denen şey, bu sürümlerin getirdiği güvenli kalıpların toplamıdır. Üniversitede hâlâ 1998 usulü C++ öğreten müfredatlarla sektörün yazdığı kod arasındaki uçurumun kaynağı da budur. Modern tarafta kalmanın pratik kuralları:

  1. auto ile tip tekrarından kurtul — derleyici zaten biliyor
  2. Ham pointer yerine unique_ptr / shared_ptr; ham dizi yerine vector / array
  3. Döngülerde index yerine range-based for: for (const auto& eleman : liste)
  4. nullptr kullan, NULL makrosunu unut
  5. Derlemede çözülebilen her şeyi constexpr ile derlemeye taşı
  6. C++20 ile geldiyse eriştiğin derleyicide: std::ranges ile begin/end çifti yazmaktan kurtul, concepts ile şablon hatalarını okunur yap

Bu kalıpların gerekçeleriyle birlikte derli toplu hâli, topluluğun ortak bakım yaptığı ISO C++ sitesi üzerindeki Core Guidelines belgesinde durur — hangi kalıbın neden tercih edildiğini merak ettiğinde ilk bakılacak yer orasıdır.

Eski usul C++ ile modern C++ kod kalıplarını yan yana karşılaştıran panel

C++ öğrenme yolculuğunun gerçekçi takvimi şöyledir: sözdizimi ve temel yapılar 1-2 ay, pointer/bellek modeli ve RAII'nin oturması 3-6 ay, STL ve modern kalıplarla rahat proje geliştirme 6-12 ay. Bu yolu sistemli bir müfredatla yürümek isteyenler C++ eğitimi ile temelden başlayabilir; klasik C++ bilen ve sürüm farklarını kapatmak isteyenler için modern C++ içerikleri ayrı bir hat olarak ilerler.

Sonuçta C++ programlama, derleyiciyle kurulan o ilk zorlu pazarlığın ödülünü yıllarca ödeyen bir yatırımdır: bellek modelini bir kez gerçekten anlayan geliştirici, hangi dile geçerse geçsin "bu kod makinede ne yapıyor" sorusunun cevabını bilerek yazar — ve o bilgi hiçbir framework'ün modası geçtiğinde eskimez.