Dinamik Bellek (new/delete)
Coddy'nin C++ Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 14 / 104.
Artık işaretçileri ve referansları anladığınıza göre, onları dinamik bellek ayırma ile işe koşalım. new ve delete operatörleri, çalışma zamanında yığında (heap) nesneler oluşturmanıza ve yok etmenize olanak tanır.
Bellek ayırmak ve ona bir işaretçi (pointer) geri almak için new kullanın:
int* num = new int; // Tek bir tam sayı ayır
*num = 42; // İşaretçi aracılığıyla değer ata
Player* player = new Player("Hero"); // Nesne ayırBelleği serbest bırakmak için her new ifadesinin eşleşen bir delete ifadesi olmalıdır:
delete num; // Tek bir nesneyi serbest bırak
delete player; // Yıkıcıyı çağırır, ardından belleği serbest bırakırDiziler için new[] ve delete[] kullanın:
int* scores = new int[5]; // 5 tam sayıdan oluşan dizi tahsis et
scores[0] = 100;
delete[] scores; // Diziyi serbest bırak - köşeli parantezlere dikkat edin!Kaçınılması gereken yaygın hatalar:
// Bellek sızıntısı - silmeyi unuttunuz
int* ptr = new int(10);
ptr = new int(20); // İlk tahsise erişim kaybedildi!
// Sarkan işaretçi (Dangling pointer) - sildikten sonra kullanma
delete ptr;
*ptr = 5; // Tanımsız davranış!
// Uyumsuz silme
int* arr = new int[10];
delete arr; // Yanlış! delete[] olmalıSildikten sonra, yanlışlıkla yeniden kullanımı önlemek için işaretçileri nullptr olarak ayarlayın. Manuel bellek yönetimi hataya açıktır; bu nedenle modern C++, bir sonraki adımda inceleyeceğimiz akıllı işaretçileri tercih eder.
Görev
Kolaynew ve delete ile dinamik bellek tahsisini gösteren basit bir mesaj depolama sistemi oluşturalım.
Kodunuzu düzenlemek için iki dosya oluşturacaksınız:
MessageBox.h: Bir dizi mesajı dinamik olarak yöneten birMessageBoxsınıfı tanımlayın. Sınıf şunlara sahip olmalıdır:- Dinamik olarak tahsis edilmiş bir string dizisine işaret eden özel (private) bir işaretçi (pointer)
- Mevcut mesaj sayısını takip eden özel (private) bir tam sayı
- Maksimum kapasiteyi saklayan özel (private) bir tam sayı
- Bir kapasite değeri alan ve
new[]kullanarak diziyi tahsis eden bir yapıcı (constructor) delete[]kullanarak belleği düzgün bir şekilde serbest bırakan ve"MessageBox destroyed"yazdıran bir yıkıcı (destructor)- Yer varsa bir mesaj ekleyen, başarı durumunda
true, doluysafalsedöndüren biraddMessage(string msg)metodu - Depolanan her mesajı kendi satırında yazdıran bir
printAll()metodu
main.cpp: Girişten bir kapasite değeri ve bir mesaj sayısı okuyun. Ardından bu sayı kadar mesaj dizesini okuyun.newkullanarak yığında (heap) birMessageBoxoluşturun, tüm mesajları ona ekleyin,printAll()metodunu çağırın ve ardından belleği serbest bırakmak için MessageBox'ı düzgün bir şekilde silin.
Giriş formatı şu şekilde olacaktır:
- İlk satır: kapasite (tam sayı)
- İkinci satır: eklenecek mesaj sayısı (tam sayı)
- Sonraki satırlar: her satırda bir mesaj
Unutmayın: her new için eşleşen bir delete ve her new[] için eşleşen bir delete[] gereklidir. Sildikten sonra, işaretçileri nullptr olarak ayarlamak iyi bir uygulamadır.
Başlık dosyanızı main.cpp içine #include "MessageBox.h" kullanarak dahil edin.
Kopya kağıdı
Yığın (heap) üzerinde dinamik olarak bellek ayırmak ve bu belleğe bir işaretçi (pointer) almak için new operatörünü kullanın:
int* num = new int; // Allocate single integer
*num = 42; // Assign value through pointer
Player* player = new Player("Hero"); // Allocate objectBelleği serbest bırakmak için her new ifadesinin eşleşen bir delete ifadesi olmalıdır:
delete num; // Free single object
delete player; // Calls destructor, then frees memoryDiziler için new[] ve delete[] kullanın:
int* scores = new int[5]; // Allocate array of 5 integers
scores[0] = 100;
delete[] scores; // Free array - note the brackets!Kaçınılması gereken yaygın hatalar:
// Memory leak - forgot to delete
int* ptr = new int(10);
ptr = new int(20); // Lost access to first allocation!
// Dangling pointer - using after delete
delete ptr;
*ptr = 5; // Undefined behavior!
// Mismatched delete
int* arr = new int[10];
delete arr; // Wrong! Should be delete[]Sildikten sonra, yanlışlıkla yeniden kullanımı önlemek için işaretçileri nullptr olarak ayarlayın.
Kendin dene
#include <iostream>
#include <string>
#include "MessageBox.h"
using namespace std;
int main() {
int capacity;
int numMessages;
// Kapasiteyi ve mesaj sayısını oku
cin >> capacity;
cin >> numMessages;
cin.ignore(); // Sayıdan sonraki yeni satır karakterini temizle
// TODO: new kullanarak heap üzerinde bir MessageBox oluştur
// TODO: Tüm mesajları oku ve MessageBox'a ekle
for (int i = 0; i < numMessages; i++) {
string message;
getline(cin, message);
// Mesajı MessageBox'a ekle
}
// TODO: Tüm mesajları görüntülemek için printAll() fonksiyonunu çağır
// TODO: Belleği boşaltmak için MessageBox'ı sil
// Sildikten sonra işaretçiyi nullptr olarak ayarlamayı unutma
return 0;
}
Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Nesne Yönelimli Programlama bölümündeki tüm dersler
1OOP Temelleri
Harici DosyalarC++ Build ve DerlemeBaşlık Dosyaları ve Kaynak DosyalarıAd Alanları ve KapsamC++'ta OOP'ye GirişSınıflar ve Nesneler'this' İşaretçisiMetotlar (Üye Fonksiyonlar)Öznitelikler (Veri Üyeleri)Ctor ve Dtor TemelleriÖzet - Basit Hesap Makinesi4Sınıf Özellikleri
Örnek ve Statik ÜyelerGetter ve Setter MetotlarıConst Üye FonksiyonlarMutable Anahtar KelimesiStatik Metotlar ve DeğişkenlerFriend Fonksiyonlar ve SınıflarÖzet - Banka Hesabı Yöneticisi7Kalıtım
Temel KalıtımKalıtım Erişim SeviyeleriCtor ve Dtor Çağrılma SırasıMetot Geçersiz KılmaSanal Fonksiyonlar ve VTableÇoklu KalıtımSanal KalıtımÖzet - Çalışan Hiyerarşisi10STL Genel Bakış
STL Genel Bakış ve FelsefesiSTL KonteynerleriİteratörlerSTL AlgoritmalarıFunctor'lar ve Lambda İfadeleriÖzet - Kelime Frekansı13Tasarım Kalıpları 1. Bölüm
Tasarım Kalıplarına GirişSingleton KalıbıFactory ve Abstract FactoryBuilder KalıbıObserver KalıbıStrategy Kalıbı2Bellek Yönetimi
Stack ve Heap Bellekİşaretçiler ve ReferanslarDinamik Bellek (new/delete)C++'ta Akıllı İşaretçilerC++'ta RAIIÖzet - Dinamik Dizi Yöneticisi5Kapsülleme
C++'da Erişim BelirleyicilerDerinlemesine Erişim BelirleyicilerBilgi GizlemeStruct vs Classİç İçe ve Dahili SınıflarÖzet - Öğrenci Kayıt Sistemi8Çok Biçimlilik
Derleme ve Çalışma Zamanı Çok BiçimliliğiFonksiyon Aşırı YüklemeSanal Fonksiyonlara Yeniden BakışSaf Sanal FonksiyonlarSoyut SınıflarC++'ta Arayüz TasarımıDynamic Casting ve RTTIÖzet - Şekil Hesaplayıcı3Yapıcılar ve Yıkıcılar
Varsayılan YapıcıParametreli YapıcıKopya YapıcıTaşıma YapıcısıYapıcı İlklendirme ListeleriTemsilci YapıcılarYıkıcılara Derinlemesine BakışÜç / Beş / Sıfır KuralıÖzet - String Sınıfı6Operatör Aşırı Yükleme
Operatör Aşırı Yüklemeye GirişAritmetik Operatör Aşırı YüklemeKarşılaştırma Operatörü Aşırı YüklemeStream OperatörleriAtama Operatörü Aşırı Yükleme[] ve () Operatör Aşırı YüklemeTip Dönüşüm OperatörleriÖzet - Matris Sınıfı9Şablonlar
Fonksiyon ŞablonlarıSınıf ŞablonlarıŞablon ÖzelleştirmeVariadic ŞablonlarSFINAE ve Type Traits TemelleriÖzet - Generic Konteyner