Yıkıcılara Derinlemesine Bakış
Coddy'nin C++ Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 24 / 104.
Bir yıkıcı (destructor), bir nesne yok edildiğinde otomatik olarak çalışan özel bir üye fonksiyondur. Temel görevi, nesnenin yaşam süresi boyunca edindiği dinamik olarak ayrılmış bellek, dosya tanıtıcıları veya ağ bağlantıları gibi kaynakları serbest bırakmaktır.
Yıkıcı metot (destructor), sınıf ile aynı ada sahiptir ve başına bir tilde ~ işareti getirilir. Hiçbir parametre almaz ve dönüş türü yoktur:
class FileHandler {
std::string filename;
int* buffer;
public:
FileHandler(std::string name, size_t size)
: filename(name), buffer(new int[size]) {
std::cout << "Opening " << filename << "\n";
}
~FileHandler() {
delete[] buffer;
std::cout << "Closing " << filename << "\n";
}
};Yıkıcılar şu durumlarda otomatik olarak çağrılır:
- Stack nesneleri kapsam dışına çıkar
- Heap üzerinde ayrılmış bir nesne için
deleteçağrılır - Geçici bir nesnenin ömrü sona erer
void example() {
FileHandler f1("data.txt", 100); // Constructor çağrıldı
FileHandler* f2 = new FileHandler("log.txt", 50);
delete f2; // f2 için Destructor çağrıldı
} // f1 için Destructor çağrıldı (kapsam dışına çıkıyor)Yapıcıların aksine, bir sınıfın yalnızca bir yıkıcısı olabilir. Onu aşırı yükleyemezsiniz.
Eğer bir tane tanımlamazsanız, derleyici özel bir şey yapmayan varsayılan bir yıkıcı (destructor) oluşturur - sadece her bir üyeyi yok eder. Kaynakları yöneten sınıflar için, bellek sızıntılarını önlemek amacıyla kendi yıkıcınızı yazmalısınız.
Görev
KolayAktif kullanıcı oturumlarını takip eden ve nesneler yok edildiğinde — ister kapsam dışına çıksınlar ister açıkça silinsinler — yıkıcıların (destructors) kaynakları nasıl otomatik olarak temizlediğini gösteren bir oturum yöneticisi oluşturalım.
Kodunuzu düzenlemek için iki dosya oluşturacaksınız:
Session.h: Dinamik olarak ayrılmış verilere sahip aktif bir kullanıcı oturumunu temsil eden birSessionsınıfı tanımlayın. Sınıfınız şunlara sahip olmalıdır:- Özel (private) üyeler: bir
username(string), birsessionId(int) ve kullanıcı eylemlerini takip edenactivityLogadında bir tam sayı dizisine işaret eden bir işaretçi (pointer) ve dizi boyutu için birlogSize - Kullanıcı adı, oturum kimliği ve günlük boyutu alan bir yapıcı (constructor). Bu yapıcı, etkinlik günlüğü dizisini yığında (heap) ayırmalı, tüm öğeleri 0'a eşitlemeli ve
"Session <sessionId> started for <username>"yazdırmalıdır - Ayrılan belleği serbest bırakan ve
"Session <sessionId> ended for <username>"yazdıran bir yıkıcı (destructor) - Etkinlik kodunu bir sonraki boş yuvaya kaydeden (mevcut konumu dahili olarak takip edin) bir
logActivity(int activityCode)metodu - Kaç etkinliğin günlüğe kaydedildiğini döndüren bir
getActivityCount()metodu - Kullanıcı adını döndüren bir
getUsername()metodu
- Özel (private) üyeler: bir
main.cpp: Farklı senaryolarda yıkıcı davranışını gösterin. Girişten bir kullanıcı adı ve günlük boyutu okuyun (her biri ayrı bir satırda), ardından:- Süslü parantezler
{ }kullanarak bir kapsam bloğu oluşturun ve içinde giriş yapılan kullanıcı adı, oturum kimliği101ve giriş yapılan günlük boyutu ile yığın üzerinde ayrılmış (stack-allocated) birSessionoluşturun.1ve2kodlarıyla iki etkinlik kaydedin, ardından"Stack session activities: <count>"yazdırın. Blok sona erdiğinde, yıkıcı otomatik olarak çalışmalıdır. - Bloktan sonra,
"Stack session destroyed"yazdırın newkullanarak"Guest"kullanıcı adı,202oturum kimliği ve3günlük boyutu ile yığında ayrılmış (heap-allocated) birSessionoluşturun.5koduyla bir etkinlik kaydedin,"Heap session activities: <count>"yazdırın, ardından bunu açıkçadeleteile silin.- Silme işleminden sonra,
"Heap session destroyed"yazdırın
- Süslü parantezler
Bu zorluk, yıkıcıların çağrılmasının iki ana yolunu gösterir: yığın nesneleri kapsamdan çıktığında otomatik olarak ve yığın (heap) nesnelerini sildiğinizde manuel olarak. Her iki yol da bellek sızıntılarını önlemek için dinamik olarak ayrılmış etkinlik günlüğünü düzgün bir şekilde serbest bırakmalıdır.
Başlık dosyanızı main.cpp içine #include "Session.h" kullanarak dahil edin.
Kopya kağıdı
Bir yıkıcı (destructor), bir nesne yok edildiğinde otomatik olarak çalışan özel bir üye fonksiyondur. Dinamik olarak ayrılmış bellek, dosya tanıtıcıları veya ağ bağlantıları gibi kaynakları serbest bırakır.
Yıkıcı, sınıf ile aynı isme sahiptir ve başına bir tilde ~ işareti alır. Parametre almaz ve geri dönüş tipi yoktur:
class FileHandler {
std::string filename;
int* buffer;
public:
FileHandler(std::string name, size_t size)
: filename(name), buffer(new int[size]) {
std::cout << "Opening " << filename << "\n";
}
~FileHandler() {
delete[] buffer;
std::cout << "Closing " << filename << "\n";
}
};Yıkıcılar şu durumlarda otomatik olarak çağrılır:
- Yığın (stack) nesneleri kapsam dışına çıktığında
- Öbekte (heap) ayrılmış bir nesne üzerinde
deleteçağrıldığında - Geçici bir nesnenin ömrü sona erdiğinde
void example() {
FileHandler f1("data.txt", 100); // Yapıcı çağrıldı
FileHandler* f2 = new FileHandler("log.txt", 50);
delete f2; // f2 için yıkıcı çağrıldı
} // f1 için yıkıcı çağrıldı (kapsam dışına çıkar)Bir sınıfın yalnızca bir yıkıcısı olabilir (aşırı yükleme yapılamaz). Eğer bir tane tanımlamazsanız, derleyici varsayılan bir yıkıcı oluşturur. Kaynakları yöneten sınıflar için, bellek sızıntılarını önlemek amacıyla kendi yıkıcınızı yazmalısınız.
Kendin dene
#include <iostream>
#include <string>
#include "Session.h"
using namespace std;
int main() {
// Girdiyi oku
string username;
int logSize;
getline(cin, username);
cin >> logSize;
// TODO: Süslü parantezler { } ile bir kapsam (scope) bloğu oluşturun
// Bloğun içinde:
// - Giriş yapılan username, oturum ID'si 101 ve giriş yapılan log size ile yığın (stack) üzerinde ayrılmış bir Session oluşturun
// - 1 ve 2 kodlarıyla iki aktivite günlüğü (log) kaydedin
// - "Stack session activities: <count>" yazdırın
// Blok sona erdiğinde, yıkıcı (destructor) otomatik olarak çalışır
// TODO: Bloktan sonra, "Stack session destroyed" yazdırın
// TODO: new kullanarak öbek (heap) üzerinde ayrılmış bir Session oluşturun
// - Username: "Guest", oturum ID: 202, log size: 3
// - 5 koduyla bir aktivite günlüğü (log) kaydedin
// - "Heap session activities: <count>" yazdırın
// - Oturumu silin (delete)
// TODO: Silme işleminden sonra, "Heap session destroyed" yazdırın
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