Middle+
İnşaatçılar və destruktorlarda istisna atma (throw exception) çağırışlarının çağrışları haqqında danış.
sobes.tech Süni İntellekt
AI-dan cavab
İşə salınan istisna konstruktor daxilində resurs sızmasına səbəb ola bilər, əgər obyektlərin və ya resursların bir hissəsi uğurla ayrılıbsa və müvafiq destruktor çağırılmayıbsa. Sızmaların qarşısını almaq üçün RAII (Resursların Əldə Edilməsi və İstifadəsi) metodundan istifadə etmək tövsiyə olunur, məsələn, ağıllı göstəricilər və ya resursların sərbəst buraxılmasını təmin edən sınaq sinifləri ilə.
Destruktor daxilində istisna atılması qeyri-müəyyən davranışa səbəb olur. Əgər destruktor başqa bir istisna nəticəsində çağırılırsa (stack unwinding), və özü işlənməyən istisna atarsa, proqram std::terminate çağırışına səbəb olacaq. C++ standartına görə, destruktorlar noexcept olmalıdır.
#include <iostream>
#include <memory> // std::unique_ptr üçün
struct Resource {
Resource() { std::cout << "Resurs əldə olundu\n"; }
~Resource() { std::cout << "Resurs sərbəst buraxıldı\n"; }
};
struct BadConstructor {
Resource res; // Resurs istisna atılmadan əvvəl ayrılacaq
BadConstructor() {
std::cout << "BadConstructor konstruktoru\n";
throw std::runtime_error("Konstruktor səhvi"); // İstisna atılır
// Resource destruktoru çağırılmayacaq, əgər istisna konstruktorun sonunda atılsa
}
~BadConstructor() noexcept { // Destruktorlar `noexcept` olmalıdır
std::cout << "BadConstructor destruktoru\n";
}
};
struct GoodConstructor {
std::unique_ptr<Resource> res; // RAII üçün ağıllı göstərici istifadə olunur
GoodConstructor() : res(std::make_unique<Resource>()) {
std::cout << "GoodConstructor konstruktoru\n";
// İstisna atılsa, unique_ptr Resource destruktorunu çağırır
// throw std::runtime_error("Konstruktor səhvi");
}
~GoodConstructor() noexcept {
std::cout << "GoodConstructor destruktoru\n";
}
};
struct BadDestructor {
BadDestructor() { std::cout << "BadDestructor konstruktoru\n"; }
~BadDestructor() {
std::cout << "BadDestructor destruktoru\n";
// Destruktor daxilində istisna atmaq olmaz
// throw std::runtime_error("Destruktor səhvi");
}
};
int main() {
// Konstruktor nümunəsi (Resurs sızmasına səbəb ola bilər)
try {
// BadConstructor bc; // Sızmanı göstərmək üçün şərh açın
} catch (const std::exception& e) {
std::cout << "İstisna tutuldu: " << e.what() << "\n";
}
// Yaxşı konstruktor nümunəsi (RAII istifadə edir)
try {
// GoodConstructor gc; // Sızma olmayacaq
} catch (const std::exception& e) {
std::cout << "İstisna tutuldu: " << e.what() << "\n";
}
// Destruktor nümunəsi (std::terminate-ə səbəb ola bilər)
try {
// BadDestructor bd; // Göstərmək üçün şərh açın
// throw std::runtime_error("Başqa istisna"); // unwind-ə səbəb olacaq
} catch (const std::exception& e) {
std::cout << "İstisna tutuldu: " << e.what() << "\n";
}
return 0;
}
Cədvəl:
| İstisna çağırış yeri | Potensial problemlər | Tövsiyə olunan həll |
|---|---|---|
| Konstruktor | Resurs sızması | RAII (ağıllı göstəricilər, sınaq sinifləri) |
| Destruktor | Qeyri-müəyyən davranış, std::terminate unwind zamanı |
Destruktorlar noexcept olmalı, istisna atmaqdan çəkinin |