#новичкам
В этом коде:
class Bar {
public:
Bar() {
throw std::runtime_error("Error");
}
};
int main() {
Bar* bar = nullptr;
try {
bar = new Bar();
} catch(...) {
std::cout << "Houston, we have a problem" << std::endl;
}
}
Не будет утечки памяти. Стандарт нам это гарантирует при использовании new expression.
Дело вот в чем. В этом посте мы поговорили о том, что есть 3 вида new:
👉🏿 operator new, который выделяет память.
👉🏿 placement new, который вызывает конструктор на заданной памяти.
👉🏿 new expression, который в начале выделяет память через operator new, а потом конструирует объект на этой памяти через placement new. Это именно то, что используется в коде выше.
Так вот, new expression заботится о своих пользователях и оборачивает в try-catch вызов конструктора объекта. В catch оно освобождает память и пробрасывает исключение наружу:
Bar* bar = new Bar();
// инструкция выше эквивалентнас следующему коду:
Bar* bar;
void* tmp = operator new(sizeof(Bar));
try {
new(tmp) Bar(); // Placement new
bar = (Bar*)tmp; // The pointer is assigned only if the ctor succeeds
}
catch (...) {
operator delete(tmp); // Deallocate the memory
throw; // Re-throw the exception
}И получается, что и исключение есть, и память освобождена. Таким образом new обеспечивает базовую гарантию исключений, чтобы программа осталась в согласованном состоянии и отсутствовали утечки памяти.
Вообще, это даже интересная техника. Ловить исключение, заметать следы преступления и пробросить исключение дальше. Может помочь избежать утечек памяти в конструкторах ваших классов, которые сами внутри выделяют память.
Спасибо, @PyXiion за предоставленную информацию)
Don't let your memory leak. Stay cool.
#cppcore #memory