Ответ 1
Стандарт не запрещает его использование в [basic.start.main] и, заставляя все реализации поддерживать не менее int main() {/*...*/ }
и int main(int argc, char* argv[]) {/*...*/}
, не ограничивает реализацию этих двух объявлений (3.6.1, пункт 2).
Из этого в отдельности было бы по крайней мере, что это законно, хотя, конечно, это касается только функций-деклараций, а не определений функций.
Чтение, [except.handle], пункт 13 гласит следующее:
Исключения, брошенные в деструкторы объектов со статическим хранилищем длительность или в конструкторах объектов пространства имен не пойманы функцией-try-block на main(). (15.3 пункт 13)
В нем упоминается блок функции-try, размещенный на main()
, что сильно означает, что такая структура является законной и имеет определенное поведение. Добавление информации о том, что main()
является только особым в его имени и типе возвращаемого значения, и что реализации не могут перегружать его, чтобы изменить какое-либо поведение, делает довольно сильный случай, когда он действует обычным образом, за исключением случаев, когда они специально отмечены, например, в выше цитаты. Другими словами, да, это законно и четко определено.
Сообщение в блоге, которое я поставил в первой версии этого ответа, на самом деле хорошо иллюстрирует правила, указанные в приведенном выше блоке, поэтому я сохраняю ссылку на него, хотя он напрямую не обсуждает проблему в вопросе OP.
Что касается комментария к OP, вы можете выдавать операторы return внутри функции-try-block, а [except.handle] имеет это сказать:
Вытекание конца функции-try-block эквивалентно возврату без ценности; это приводит к поведению undefined при возврате значения функции (6.6.3). (15.3 пункт 15)
Если вы находитесь в блоке catch в конце main
, вы не собираетесь перетекать через тело функции (в данном случае это будет блок try), поэтому автоматически это правило звонки return 0;
при потоке не применяются. Вам нужно вернуть int
(возможно, код ошибки), чтобы он не становился undefined.