Назад к вопросам
Middle+
77
questionbank
О чем следует помнить при выбросе исключений в конструкторе?
Sobes Copilot
Получайте ответы в реальном времени
Ответ от нейросети
sobes.tech AI
- Утечки ресурсов: Если конструктор выбросил исключение после того, как часть ресурсов была выделена (память, дескрипторы файлов и т.д.), но до завершения инициализации объекта, эти ресурсы могут не быть освобождены, если деструктор объекта не будет вызван.
- Частично построенные объекты: Объект, конструктор которого выбросил исключение, считается недостроенным. Деструктор для такого объекта не вызывается автоматически.
- RAII (Resource Acquisition Is Initialization): Использование RAII-оберток (например,
std::unique_ptr,std::vector,std::lock_guard) для управления ресурсами помогает автоматически освобождать их при выбросе исключения, поскольку деструкторы RAII-объектов, используемых в конструкторе, вызываются при раскрутке стека. - Порядок инициализации членов: Члены класса инициализируются в порядке их объявления, а не в порядке их инициализации в списке инициализации конструктора. Если инициализация члена выбросила исключение, то члены, проинициализированные до этого, могут потребовать очистки.
noexcept: Конструктор класса сnoexceptспецификатором не должен выбрасывать исключения. Если исключение выбрасывается вnoexceptконструкторе, программа будет завершена (default behaviour).newоператор: Сам операторnewможет выбросить исключениеstd::bad_allocпри нехватке памяти.
Пример использования RAII:
#include <memory>
#include <stdexcept>
class Resource {
public:
Resource() { /* Выделение ресурса */ }
~Resource() { /* Освобождение ресурса */ }
};
class MyClass {
std::unique_ptr<Resource> res1;
std::unique_ptr<Resource> res2;
public:
MyClass() : res1(std::make_unique<Resource>()) {
// Если здесь будет выброшено исключение, res1 освободится
if (/* условие для исключения */ true) {
throw std::runtime_error("Error during construction");
}
res2 = std::make_unique<Resource>(); // Эта строка не будет достигнута
}
};
int main() {
try {
MyClass obj;
} catch (const std::exception& e) {
// res1 будет освобожден автоматически благодаря unique_ptr
// res2 никогда не был создан
}
return 0;
}