Оновлено, дивіться нижче!
Я чув і читав, що C ++ 0x дозволяє компілятору надрукувати "Привіт" для наступного фрагмента
#include <iostream>
int main() {
while(1)
;
std::cout << "Hello" << std::endl;
}
Це, мабуть, має щось спільне з потоками та можливостями оптимізації. Мені здається, що це може здивувати багатьох людей.
Хтось має добре пояснення, чому це потрібно було дозволити? Для довідки, останній C ++ 0x чернетка говорить на6.5/5
Цикл, який за межами for-init-заяви у випадку заяви для заяви,
- не здійснює дзвінків до функцій вводу / виводу бібліотеки та
- не отримує доступу та не змінює летючі об'єкти;
- не виконує жодних операцій синхронізації (1.10) або атомних операцій (п. 29)
може припускати, що реалізація припиняється. [Примітка: Це призначено для того, щоб дозволити трансформації компілятора, такі як видалення порожніх циклів, навіть коли припинення неможливо довести. - кінцева примітка]
Редагувати:
Ця прониклива стаття говорить про цей текст Стандартів
На жаль, слова "невизначена поведінка" не вживаються. Однак у будь-який час, коли стандарт каже, що "компілятор може вважати P", мається на увазі, що програма, яка має властивість not-P, має невизначену семантику.
Це правильно, і чи дозволяється компілятору надрукувати "Bye" для вищевказаної програми?
Тут є ще більш проникливий потік , який стосується аналогічної зміни на C, розпочатої хлопцем, виконаною вище зв'язаною статтею. Серед інших корисних фактів вони представляють рішення, яке, здається, також стосується C ++ 0x ( оновлення : з n3225 це більше не працюватиме - див. Нижче!)
endless:
goto endless;
Здається, компілятору не дозволяється оптимізувати це, бо це не цикл, а стрибок. Інший хлопець підсумовує запропоновані зміни у C ++ 0x та C201X
Записуючи цикл, програміст запевняє або про те, що цикл робить щось із видимою поведінкою (виконує введення-виведення, доступ до летючих об'єктів або виконує синхронізацію чи атомні операції), або що він врешті-решт припиняється. Якщо я порушую це припущення, написавши нескінченний цикл без побічних ефектів, я брешу на компілятор, і поведінка моєї програми не визначена. (Якщо мені пощастить, компілятор може попередити мене про це.) Мова не забезпечує (більше не надає?) Спосіб виразити нескінченний цикл без видимої поведінки.
Оновлення 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(); }
повинні бути самостійно складені, не знаючи визначення цієї загадкової функції, правда? Тож як ми можемо визначити, чи здійснює він дзвінки до будь-яких функцій вводу / виводу бібліотеки? Іншими словами: напевно, що перша куля могла бути сформульована, не викликає функцій .