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.
Yıkıcı, bir nesne yok edildiğinde otomatik olarak çalıştırılan özel bir üye işlevidir. 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ının adı sınıfla aynıdır ve başına bir tilde ~ eklenir. 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";
}
};Yok ediciler şu durumlarda otomatik olarak çağrılır:
- Yığın nesneleri kapsam dışına çıkar
- Yığın üzerinde ayrılmış bir nesne için
deleteçağrılır - Geçici bir nesnenin yaşam süresi sona erer
void example() {
FileHandler f1("data.txt", 100); // Kurucu ç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)Yapıcıların aksine, bir sınıfın yalnızca bir yıkıcısı olabilir. Onu aşırı yükleyemezsiniz.
Bir tane tanımlamazsan, derleyici özel bir işlem yapmayan varsayılan bir yıkıcı oluşturur; yalnızca her ü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
KolayEtkin kullanıcı oturumlarını izleyen ve nesneler yok edildiğinde, kapsam dışına çıksalar ya da açıkça silinseler de yıkıcıların kaynakları otomatik olarak nasıl 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ış veriler içeren etkin bir kullanıcı oturumunu temsil eden birSessionsınıfı tanımlayın. Sınıfınız şunlara sahip olmalıdır:- Özel üyeler: bir
username(dize), birsessionId(tamsayı) ve kullanıcı eylemlerini izleyen,activityLogadlı bir tamsayı dizisine işaretçi; ayrıca dizinin boyutu için birlogSize - Bir kullanıcı adı, oturum kimliği ve günlük boyutu alan bir oluşturucu. Oluşturucu, etkinlik günlüğü dizisini heap üzerinde ayırmalı, tüm öğeleri 0 olarak başlatmalı 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ı - Etkinlik kodunu bir sonraki kullanılabilir yuvaya kaydeden bir
logActivity(int activityCode)yöntemi (geçerli konumu dahili olarak izleyin) - Günlüğe kaç etkinlik kaydedildiğini döndüren bir
getActivityCount()yöntemi - Kullanıcı adını döndüren bir
getUsername()yöntemi
- Özel üyeler: bir
main.cpp: Farklı senaryolarda yıkıcı davranışını gösterin. Girdiden bir kullanıcı adı ve günlük boyutu okuyun (her biri ayrı bir satırda), ardından:- Süslü parantezlerle
{ }bir kapsam bloğu oluşturun ve bu bloğun içinde, girdi olarak alınan kullanıcı adı,Sessionoturum kimliği ve girdi olarak alınan günlük boyutuyla stack üzerinde ayrılmış bir101oluşturun.1ve2kodlarıyla iki etkinlik günlüğe 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 - Kullanıcı adı
Session, oturum kimliğinewve günlük boyutu"Guest"ile202kullanarak heap üzerinde ayrılmış bir3oluşturun.5koduyla bir etkinlik günlüğe kaydedin,"Heap session activities: <count>"yazdırın ve ardından açıkçadeleteuygulayın. - Silme işleminden sonra
"Heap session destroyed"yazdırın
- Süslü parantezlerle
Bu alıştırma, yıkıcıların çağrılmasının iki temel yolunu gösterir: stack nesneleri kapsamdan çıktığında otomatik olarak ve 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 şekilde serbest bırakmalıdır.
Başlık dosyanızı #include "Session.h" kullanarak main.cpp dosyasına ekleyin.
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ü parantezlerle { } bir kapsam bloğu oluştur
// Bloğun içinde:
// - Girdi kullanıcı adıyla, oturum kimliği 101 ve girdi log boyutuyla yığın-ayrılmış bir Session oluştur
// - 1 ve 2 kodlarıyla iki aktivite kaydet
// - Print "Stack session activities: <count>"
// Blok bittiğinde, yıkıcı otomatik olarak çalışır
// TODO: After the block, print "Stack session destroyed"
// TODO: new kullanarak öbek-ayrılmış bir Session oluştur
// - Kullanıcı adı: "Guest", oturum kimliği: 202, log boyutu: 3
// - 5 koduyla bir aktivite kaydet
// - Print "Heap session activities: <count>"
// - Oturumu sil
// TODO: After deletion, print "Heap session destroyed"
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 KonteynerKendi başına pratik yap: Online C++ derleyicisi