Dinamik Bellek Yönetimi: new ve delete
Heap tahsisi, new/delete kullanımı ve RAII’ye hazırlık için en iyi pratikler.
C++ dilinde belleğin iki ana bölgesi vardır: Stack (yığın) ve Heap (küme).
Stack alanı otomatik olarak yönetilirken, Heap alanındaki bellek programcı tarafından manuel olarak kontrol edilir.
Dinamik bellek yönetimi, program çalışırken bellek ayırmak ve serbest bırakmak için kullanılır.
Bu makalede new ve delete anahtar kelimeleriyle dinamik bellek kullanımını detaylı inceleyeceğiz.
1. Stack ve Heap Arasındaki Fark
| Özellik | Stack (Otomatik) | Heap (Dinamik) |
|---|---|---|
| Yönetim | Otomatik (derleyici tarafından) | Programcı tarafından manuel |
| Yaşam süresi | Fonksiyon bitince otomatik silinir | Programcı silmezse bellekte kalır |
| Hız | Çok hızlı | Daha yavaştır (dinamik yönetim) |
| Bellek boyutu | Kısıtlı | Daha geniş |
| Kullanım | Yerel değişkenler | Dinamik nesneler, diziler |
2. new Anahtar Kelimesi ile Bellek Ayırma
new operatörü, Heap üzerinde dinamik olarak bellek ayırır ve ayrılan belleğin adresini döndürür.
Bu adres genellikle bir pointer değişkene atanır.
#include <iostream>
using namespace std;
int main() {
int *ptr = new int; // 1 adet int için bellek ayır
*ptr = 42;
cout << "Değer: " << *ptr << endl;
delete ptr; // Belleği serbest bırak
ptr = nullptr; // Güvenli hale getir
}
Not: new ile ayrılan bellek, delete ile manuel olarak serbest bırakılmalıdır.
Aksi halde bellek sızıntısı (memory leak) oluşur.
3. new ile Dinamik Diziler
Dinamik olarak dizi oluşturmak için new[] kullanılır.
Boyut çalışma zamanında belirlenebilir.
#include <iostream>
using namespace std;
int main() {
int n;
cout << "Kaç elemanlı dizi istiyorsunuz? ";
cin >> n;
int *dizi = new int[n]; // n elemanlık dizi oluştur
for (int i = 0; i < n; i++)
dizi[i] = (i + 1) * 10;
cout << "Dizi: ";
for (int i = 0; i < n; i++)
cout << dizi[i] << " ";
delete[] dizi; // Belleği serbest bırak
dizi = nullptr;
}
delete[] kullanımı önemlidir;
normal delete sadece tek değişken için geçerlidir, dizilerde kullanılmaz.
4. Dinamik Bellek Ayırma ve Serbest Bırakma Adımları
- new → Heap üzerinde bellek ayırır.
- Pointer → Ayrılan bellek adresini tutar.
- Veri işlenir veya doldurulur.
- delete / delete[] → Bellek serbest bırakılır.
- Pointer = nullptr → Asılı (dangling) pointer engellenir.
5. Bellek Sızıntısı (Memory Leak) Nedir?
Dinamik olarak ayrılan belleğin serbest bırakılmaması durumunda bellekte kullanılmayan alanlar birikir. Bu duruma bellek sızıntısı denir ve uzun süre çalışan programlarda ciddi performans sorunlarına yol açabilir.
void OlumsuzOrnek() {
int *p = new int(10);
// delete p; // Unutuldu! Bellek sızıntısı
}
Çözüm: delete kullanarak bellek serbest bırakılmalıdır.
6. nullptr ve Bellek Güvenliği
C++11 öncesinde boş pointer’lar genellikle NULL ile temsil edilirdi.
Modern C++’ta bunun yerine tür güvenli nullptr anahtar kelimesi kullanılır.
int *p = nullptr;
if (p == nullptr) {
cout << "Pointer hiçbir adresi göstermiyor." << endl;
}
nullptr kullanmak, yanlış adres erişimlerini ve “çökme” hatalarını (segmentation fault) önlemeye yardımcı olur.
7. Dinamik Bellek ile Fonksiyon Kullanımı
Bellek dinamik olarak oluşturulup fonksiyona gönderilebilir. Bu yöntem özellikle dinamik dizilerde yaygındır.
void Doldur(int *p, int n) {
for (int i = 0; i < n; i++)
p[i] = (i + 1) * 2;
}
int main() {
int *dizi = new int[5];
Doldur(dizi, 5);
for (int i = 0; i < 5; i++)
cout << dizi[i] << " ";
delete[] dizi;
}
8. new ile Obje Oluşturma
new sadece temel veri türlerinde değil, sınıf nesnelerinde de kullanılabilir.
#include <iostream>
using namespace std;
class Ogrenci {
public:
string ad;
Ogrenci(string a) : ad(a) {
cout << ad << " oluşturuldu." << endl;
}
~Ogrenci() {
cout << ad << " silindi." << endl;
}
};
int main() {
Ogrenci *p = new Ogrenci("Ali");
delete p; // destructor çağrılır
}
new ile oluşturulan nesnelerin delete ile silinmesi,
otomatik olarak o nesnenin destructor metodunu çağırır.
9. Smart Pointer’lar (Modern C++ Yaklaşımı)
C++11 ile birlikte manuel delete işlemlerine alternatif olarak
akıllı pointer’lar (smart pointers) tanıtılmıştır.
Bunlar otomatik bellek yönetimi sağlar.
- std::unique_ptr → Tek sahipli pointer (kopyalanamaz)
- std::shared_ptr → Paylaşılan sahiplik (referans sayımı)
- std::weak_ptr → Paylaşılan pointer’lara zayıf referans
#include <iostream>
#include <memory>
using namespace std;
int main() {
unique_ptr<int> p = make_unique<int>(100);
cout << *p << endl; // 100
}
Smart pointer’lar, nesne kapsamdan çıktığında belleği otomatik olarak serbest bırakır. Bu sayede bellek sızıntıları ortadan kalkar.
10. TL;DR
new→ Heap üzerinde bellek ayırır, adres döndürür.delete→ Belleği serbest bırakır (tek değişken).new[] / delete[]→ Dinamik diziler için kullanılır.nullptr→ boş pointer için güvenli tanımdır.- Bellek sızıntılarını önlemek için her
new’e karşılık birdeleteolmalıdır. std::unique_ptrvestd::shared_ptrmodern alternatiflerdir.- Tüm örnekler Visual Studio 2022 veya GCC 11+ ortamında çalıştırılabilir.