неудачный конструктор и неудачный деструктор в C ++ - PullRequest
4 голосов
/ 26 февраля 2010

У меня один вопрос о неудачном конструкторе и неудачном деструкторе в C ++.

Я заметил, что при сбое конструктора будет выдано исключение. Но в деструкторе не исключение.

Мой вопрос

1) Если конструктор не удался, какое исключение будет выдано? bad_alloc? или еще что-нибудь связанное? При какой ситуации конструктор потерпит неудачу? А как насчет успешно построенной детали?

2) При какой ситуации деструктор потерпит неудачу? Если не будет выброшено исключение, что произойдет с деструктором? Как с этим справится компилятор? Какое значение возвращается функции, которую она вызывает?

Спасибо!

Любые комментарии приветствуются!

Ответы [ 6 ]

6 голосов
/ 26 февраля 2010
  1. Если конструктор терпит неудачу, исключение выдается, только если конструктор реализован так, что он выдает исключение. (Возможно, вам придется различать распределение памяти и конструкцию. Выделение памяти с использованием new может привести к ошибке std::bad_alloc.)

  2. Не бывает случаев, когда конструктор вообще терпит неудачу. Это терпит неудачу, только если это написано так, чтобы это могло потерпеть неудачу. Если да, то, как это не удастся, зависит от того, как оно написано. В общем, деструкторы должны быть написаны так, чтобы они не выходили из строя, поскольку небезопасно создавать исключения из деструкторов. (Это потому, что они могут быть вызваны при размотке стека.)

Обратите внимание, что "сбой", используемый в вашем вопросе, обычно относится к сбоям во время выполнения. Таким образом, компилятор не имеет к этому никакого отношения. Кроме того, ни конструкторы, ни деструкторы ничего не возвращают.

2 голосов
/ 26 февраля 2010

Если ваш деструктор выдает исключение, вы делаете что-то не так. Создание исключения в деструкторе может привести к нескольким проблемным областям: элементы, используемые из пулов сокетов / потоков / объектов, могут стать постоянно захваченными в необратимом состоянии, память может быть не освобождена, или логика, которая по какой-то причине вы поместили в деструктор, может не позвонить.

Все те же причины, по которым исключение может быть вызвано в другом коде, могут вызвать исключение в деструкторе. В частности, если у вас есть где-то висящий указатель, попытка очистить используемую в данный момент память может вызвать системное исключение. Удачи в этом.

2 голосов
/ 26 февраля 2010

Исключение, которое выдается при сбое конструктора, определяется самим конструктором, либо потому, что он выбрасывает напрямую, либо действиями, которые он выполняет (например, вызов другой функции, которая может вызвать исключение).

Конструкторы могут потерпеть неудачу, когда они пытаются получить ресурс, который недоступен, например, память, дескриптор файла, окно экрана и т. Д. Если new не удастся, он выдаст std::bad_alloc. Если конструктор не поймает его, это будет распространяться за пределы конструктора.

C ++ не имеет хорошего способа справляться с ошибками в деструкторе. Насколько это возможно, вы должны проектировать деструкторы, чтобы не потерпеть неудачу. Вы никогда не должны бросать исключение из деструктора. И если функция, которую вы вызываете в деструкторе, может вызвать исключение, вы должны либо перехватить его (если вы знаете, что его можно игнорировать), либо немедленно завершить работу.

1 голос
/ 26 февраля 2010

В дополнение ко всему, что упомянуто здесь, оператор new может выдать bad_alloc до вызова конструктора. Конструктор начинает работать только после того, как часть памяти существует для экземпляра объекта, в котором он существует (хотя он не существует полностью, пока конструктор не завершится).

1 голос
/ 26 февраля 2010

Если конструктор дает сбой, он выдает какое-то исключение. Это не должно быть, потому что память не может быть выделена; все, что выкинуло исключение, приведет к сбою, включая throw операторы, которые вы пишете сами. Идея обычно заключается в том, чтобы создать пригодный для использования объект или создать исключение.

Если конструктор дает сбой, то успешно созданная деталь отсутствует. Все прошло.

Я не знаю, что означает неудачный деструктор. Он выполнит любой применимый код и ничего не вернет. Если код написан плохо, он может не выполнить то, что хочет программист, но это верно для всех функций.

Деструкторы никогда не должны бросать исключения. (Они могут вызывать подпрограммы, которые выдают, но они должны перехватывать все исключения и сами с ними разбираться.) Если деструктор выбрасывает, и он вызывается потому, что было сгенерировано исключение, и он разматывает стек, программа вылетает так или иначе. (Существуют механизмы, позволяющие определить, раскручивается ли стек или нет, но в лучшем случае вы пишете деструктор двумя разными способами, и их сложно проверить обоими.)

1 голос
/ 26 февраля 2010

Конструктор в этом контексте «просто» пользовательская функция, она может генерировать любые исключения, которые она хочет. Если конструктор не выдает исключение, он считается неуспешным.

Итак: конструктор не терпит неудачу сам по себе. Если он выдает исключение сам, это не удалось. Если этого не произойдет, компилятор не добавит никакого специального кода для выдачи каких-либо исключений.

То же самое относится и к деструкторам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...