Обновлено, смотрите ниже!
Я слышал и читал, что C ++ 0x позволяет компилятору напечатать «Hello» для следующего фрагмента
#include <iostream>
int main() {
while(1)
;
std::cout << "Hello" << std::endl;
}
По-видимому, это как-то связано с потоками и возможностями оптимизации. Мне кажется, что это может удивить многих людей, хотя.
У кого-нибудь есть хорошее объяснение того, почему это необходимо было разрешить? Для справки, самый последний проект C ++ 0x гласит:6.5/5
Цикл, который вне оператора for-init-в случае оператора for,
- не вызывает функции библиотеки ввода-вывода, и
- не получает доступ и не изменяет изменчивые объекты, и
- не выполняет операции синхронизации (1.10) или атомарные операции (пункт 29)
реализация может быть прекращена. [Примечание: это предназначено для разрешения преобразований компилятора, таких как удаление пустых циклов, даже если завершение не может быть доказано. - конец примечания]
Редактировать:
Эта проницательная статья говорит о том, что текст стандартов
К сожалению, слова «неопределенное поведение» не используются. Однако всякий раз, когда в стандарте говорится, что «компилятор может принять P», подразумевается, что программа со свойством not-P имеет неопределенную семантику.
Это правильно, и разрешено ли компилятору печатать «пока» для вышеуказанной программы?
Здесь есть еще более проницательная тема , посвященная аналогичному изменению C, начатая парнем из вышеупомянутой связанной статьи. Среди других полезных фактов они представляют решение, которое, похоже, также применимо к C ++ 0x ( обновление : это больше не будет работать с n3225 - см. Ниже!)
endless:
goto endless;
Кажется, компилятору не разрешено оптимизировать это, потому что это не цикл, а скачок. Другой парень обобщает предложенное изменение в C ++ 0x и C201X
При написании цикла, программист утверждать , либо , что петля делает что - то с видимым поведением (выполняют I / O, получает доступ летучих объектов, или выполняет синхронизацию или атомарные операции), или , что он в конечном итоге заканчивается. Если я нарушу это предположение, написав бесконечный цикл без побочных эффектов, я лгу компилятору, и поведение моей программы не определено. (Если мне повезет, компилятор может предупредить меня об этом.) Язык не предоставляет (больше не предоставляет?) Способ выразить бесконечный цикл без видимого поведения.
Обновление 3.1.2011 с n3225: Комитет переместил текст в 1.10 / 24 и произнес
Реализация может предполагать, что любой поток в конечном итоге выполнит одно из следующих действий:
- прекратить,
- сделать вызов функции ввода-вывода библиотеки,
- получить доступ или изменить изменчивый объект, или
- выполнить операцию синхронизации или атомарную операцию.
goto
Трюк будет не работать больше!
int x = 1; for(int i = 0; i < 10; ++i) do_something(&i); x++;
на for(int i = 0; i < 10; ++i) do_something(&i); int x = 2;
? Или, возможно, другой путь, с x
инициализацией 2
до цикла. Он может сказать, do_something
что не заботится о значении x
, поэтому это совершенно безопасная оптимизация, если do_something
она не приводит i
к изменению значения так, что вы попадаете в бесконечный цикл.
main() { start_daemon_thread(); while(1) { sleep(1000); } }
может просто завершиться немедленно вместо запуска моего демона в фоновом потоке?
while(1) { MyMysteriousFunction(); }
должен быть независимо компилируемым, не зная определения этой загадочной функции, верно? Итак, как мы можем определить, выполняет ли он какие-либо функции библиотеки ввода-вывода? Другими словами: конечно, первая фраза, которую можно сформулировать, не вызывает функций .