Обновление : обеспокоенный комментарием @Pete Becker, я исправляю свой ответ на это:
Ваш код плохо сформирован и из-за этого вызывает так называемое неопределенное поведение не поведение, определяемое реализацией .
Однако этот вывод не является полностью безопасным, так как мы входим здесь в часть языковой адвокатуры.
Неопределенное поведение (UB) определяется как
поведение, для которого этот международный стандарт не предъявляет никаких требований, что обычно означает: не пытайтесь рассуждать об этом коде и никогда не используйте его.
Вопрос в том, определяет ли C ++ требования к вашему коду, т. е. является ли ваш код правильно сформированная программа ? Тогда это будет определенное поведение (обычное поведение), неопределенное поведение или даже квалификация этого поведения, определенного реализацией . Но в 20.5.2.2 Заголовки [using.headers] стандарт C ++ гласит:
Единица перевода должна включать заголовок только вне любого объявления или определения и должна включать заголовок лексически перед первой ссылкой в этом блоке перевода любому из объектов, объявленных в этом заголовке. Диагностика c не требуется.
Согласно Разница между неопределенным поведением и плохим формированием, сообщение о диагностике c не требуется это будет означать неопределенное поведение, даже если оно прямо не нарушает 6.2 Правило единого определения , которое в вашем случае должно было бы быть нарушено, чтобы быть плохо сформированной программой , но как ответ на уже указанный вопрос что по умолчанию в этом правиле задано неопределенное поведение, и если нет точно одного определения, у нас здесь плохо сформированная программа.
Старая часть: простой, но неудовлетворительный ответ: так называемое поведение, определяемое реализацией. Компилятор Microsoft Visual C ++ и его заголовки могут свободно включать друг друга, возможно, заголовок MSVC iostream
уже включает cmath
, по крайней мере, транзитивно, если не напрямую.
Веселье начинается, если вы попытаетесь скомпилировать тот же код с помощью g cc или clang. Внезапные пропущенные включения - это, по крайней мере, наиболее распространенные переносимые ошибки в моем коде.
Если вы фактически включаете каждый заголовок, который, как говорит стандарт, требуется, то есть содержит определения того, что вы используете, вы получаете так называемый portable код , означающий код, который будет компилироваться и делать то же самое независимо от использования MSVC / Visual Studio или g cc или clang или любого другого стандартного совместимого компилятора.