Если любой из этих бросков
class X {
string m_str;
X() : m_str("foo")//what if this throws?
{
ifstream b("a.in")//what if this throws?
}
Тогда созданный вами объект не будет существовать.
Если в конструктор объекта выдается исключение, то все полностью созданные члены уничтожаются (используя их деструктор), и память для объекта возвращается в систему. Таким образом, любые члены, которые не полностью построены в точке выброса, не будут уничтожены (так как они не были созданы).
- Если m_str () выбрасывает в списке инициализатора, объект никогда не будет существовать.
- Если ifstream выбрасывает тело, m_str уничтожается и объект никогда не будет существовать.
Должен ли я обернуть код в catch (исключение &)? И если я сделаю это, гарантирует ли string и ifstream надежную гарантию, что никакие ресурсы не просочились и ничего не осталось наполовину открытым?
Даже если вы перехватываете исключение (за пределами объекта), нет объекта, с которым можно работать, поскольку он никогда не существовал (срок жизни объекта начинается только после завершения конструктора).
В приведенном выше вы гарантированно нет утечек или открытых ресурсов.
Кроме того, если мой класс выбрасывает myexception, полученное из исключения, catch (exception &), кажется, пропускает его. Так что у меня остается с catch (...), какой IIRC ловит нарушение доступа? Есть ли другой способ?
Если ваше исключение получено из std :: exception, тогда catch(std::exception&)
будет работать. Если это не работает, значит, вы делаете что-то не так (но нам нужно больше подробностей (например, код, который выдает, и код, который перехватывает, описание на английском не подходит)).
Затем где-то была информация, что не должно быть перехвачено любое исключение, выброшенное в субконструкторах конструктора объекта, и конструктор должен выдать в случае, если какой-либо объект-член выдает.
Вероятно, лучший вариант и, как правило, неплохой совет.
А что если код выше был бы вызван не из конструктора, а из обычной функции void foo (), какие исключения я должен перехватить? outofmemory_something, файл notfound_something? Где я могу найти определения того, что могут генерировать объекты STL? Они специфичны для реализации?
Вы должны ловить исключения, только если можете что-то с этим сделать. Обычно в этом нет ничего особенного; если вы поймаете их, пусть приложение завершит работу нормально (за исключением разматывания стека).
Где находится авторитетный источник, где я мог бы прояснить все мои сомнения и вопросы по этой теме?
Ваш вопрос настолько разнообразен, что это сложно.
Я мог бы рекомендовать "Исключительный C ++" Хербом Саттером .
До сих пор кажется, что обработка исключений подобна танцу в большой куче оооочень. Коды ошибок кажутся намного проще и безопаснее ...
Вы не правы там. Исключения намного проще. Вы просто, кажется, слишком обдумали это и запутались. Это не означает, что коды ошибок не имеют своего места.
Если что-то пойдет не так and you can not fix it locally
, тогда выведите исключение. Все классы в стандарте разработаны с учетом исключений и будут вести себя правильно. Так что это просто оставляет ваши уроки.
Эмпирические правила: (для ваших объектов)
- Убедитесь, что ваши классы убираются в деструкторе
- Если ваш объект содержит ресурсы, убедитесь, что «соблюдается правило 3»
- Никогда не иметь более одного ресурса на объект.
Примечание: у вас может быть несколько вещей, таких как std :: string или std :: ifstream, так как они управляют ресурсом (каждый из них контролирует один ресурс, поэтому ваш класс не контролирует ресурс). Ресурс (в этом контексте) - это то, что вы должны вручную создать / уничтожить.
Вот и все, все остальное работает автоматически.