Исключения в конструкторе и утечка памяти на C++
Вот допустим у меня есть такой класс:
class A {
std::string str;
int *ptr;
public:
A(std::string& str) : str(str), ptr(new int(2)) {
if (str.size() == 5) {
throw std::runtime_error("ERROR");
}
}
~A() {
delete ptr;
}
};
Понятно, что из-за вызова исключения в конструкторе должны вызваться деструкторы всех локальных элементов класса. Поскольку локальные элементы находятся в стеке, то для поля str деструктор вызовется, но ведь поле ptr находится не на стеке, а в heap, откуда элементы нужно удалять вручную. В связи с чем и возник вопрос: правильно ли я понимаю, что для поля ptr деструктор не будет вызван, поскольку это не локальная переменная, которая хранится в стеке, а переменная, хранящаяся в heap, и в итоге на протяжении всей программы у нас мало того, что будет неосвобожденная память на стеке от объекта класса A, поскольку деструктор так и не был вызван, так еще и неосвобожденная память в heap от поля ptr (утечка памяти в двух местах)?
Ответы (1 шт):
поле ptr находится не на стеке
Член ptr находится там, где создается объект A, а в стеке это или где еще — вопрос второй. А вот память, на которую он указывает, будет в куче, и действительно не будет освобождена, так как пока конструктор не завершится, объекта нет, и деструктор вызван не будет.
Говорить об "утечке" от локального объекта не приходится, так как по выходе из функции стековая память просто будет "освобождена" (это немного не то освобождение, что при delete — она просто будет использована при последующих вызовах. Но вот если создавать объект в куче через new A — ситуация усложняется...
Все эти вопросы достаточно тщательно разобраны в книгах Саттера "Решение сложных задач на С++" и "Новые сложные задачи на С++", несмотря на то, что изданы они еще до появления C++11.