C ++: обрабатывать ресурсы, если конструкторы могут генерировать исключения (ссылка на FAQ 17.4]
7424 просмотра
4 ответа
Спасибо за все ответы.
Я переформатировал свой вопрос, чтобы понять состояние указателя на член после того, как конструктор связывающегося класса выдает исключение
Опять мой пример класса :)
class Foo
{
public:
Foo()
{
int error = 0;
p = new Fred;
throw error; // Force throw , trying to understand what will happen to p
}
~Foo()
{
if (p)
{
delete p;
p = 0;
}
}
private:
Fred* p;
};
int main()
{
try
{
Foo* lptr = new Foo;
}
catch (...)
{}
}
Consturctor для класса foo выдает исключение по какой-то случайной причине. Я понимаю, что деструктор foo никогда не будет вызван, но в этом случае деструктор для p будет вызван?
какая разница, если p - умный указатель для повышения, чем для необработанного указателя на fred.
Благодарю.
Автор: mithuna Источник Размещён: 13.11.2019 11:43Ответы (4)
6 плюса
Здесь есть похожий вопрос, который охватывает то, что вы спрашиваете.
В этом случае, если вызов new
завершится неудачно, память для указателя будет гарантированно освобождена. Если вызов завершится успешно, и после этого сработает конструктор, у вас будет утечка памяти.
Деструктор класса не будет вызван, потому что объект никогда не был полностью построен. Есть два способа это исправить.
1)
Имейте полностью управляемые исключения в конструкторе:
class Foo
{
public:
Foo()
try
{
p = new p;
throw /* something */;
}
catch (...)
{
delete p;
throw; //rethrow. no memory leak
}
private:
int *p;
};
2)
Или используйте умный указатель. Когда конструктор введен, все его члены были построены. И потому, что когда конструктор выбрасывает объекты и члены конструируются, они должны быть уничтожены. И умный указатель исправляет это:
class Foo
{
public:
Foo() :
p(new int)
{
throw /* something */;
}
private:
std::auto_ptr<int> p;
};
Автор: GManNickG
Размещён: 05.08.2009 12:14
2 плюса
Нет, если это никогда не было выделено.
Но вместо того, NULL
чтобы возвращаться при неправильном распределении через new, вы получите исключение std :: bad_alloc.
NULL
возвращается malloc C, если распределение не может быть сделано.
Вы также правы, что, если объект не полностью построен, он не будет разрушен. Таким образом, если у вас есть успешное размещение в куче в конструкторе, и затем выдается исключение, это приведет к утечке памяти.
Вы также можете подумать о том, чтобы иметь состояние зомби, а не создавать исключение. Некоторые из стандартных библиотек C ++ делают это. В этом случае объект не находится в допустимом состоянии и может быть проверен, если он находится в допустимом состоянии с помощью другого метода.
Вообще, бросать исключения в конструкторы лучше всего.
Смотрите мой ответ здесь для расширенного обсуждения .
Автор: Brian R. Bondy Размещён: 04.08.2009 11:281 плюс
Деструктор для p
не будет вызван, если выделение памяти для p
не удастся.
1 плюс
Вопрос действительно не имеет никакого смысла. new Fred();
никогда не вернет NULL. Он только когда-либо либо успешно создаст объект Fred, либо выдаст исключение. Если бы он вызвал исключение, объект Fred никогда бы не существовал, поэтому его деструктор не был бы вызван.
Вопросы из категории :
- c++ What are the barriers to understanding pointers and what can be done to overcome them?
- c++ Какой самый простой способ для анализа файла INI в C ++?
- c++ Когда вы должны использовать «друг» в C ++?
- c++ Как вы очищаете переменную stringstream?
- c++ В C ++ конструктор и деструктор могут быть встроенными функциями?
- c++ Что такое виртуальный базовый класс в C ++?
- c++ В чем разница между #include <filename> и #include "filename"?
- c++ Какой самый лучший бесплатный детектор утечки памяти для программы на C / C ++ и ее подключаемых библиотек DLL?
- c++ Как преобразовать std :: string в LPCWSTR в C ++ (Unicode)
- c++ Regular cast vs. static_cast vs. dynamic_cast
- exception Неужели так плохо поймать общее исключение?
- exception Когда выбирать отмеченные и непроверенные исключения
- exception Возвращаясь из блока finally в Java
- exception Как сбросить InnerException без потери трассировки стека в C #?
- exception Когда для конструктора правильно выбрасывать исключение?
- exception Работа с ошибкой "java.lang.OutOfMemoryError: PermGen space"
- exception Почему переменные не объявлены в «try» в области «catch» или «finally»?
- exception Какие и почему вы предпочитаете исключения или коды возврата?
- exception Причины получения java.lang.VerifyError
- exception Обобщенная обработка исключений в Python "Правильный путь"