Я подозреваю, что мы путаем две концепции. Порядок вызовов был исправлен только в выражениях в c ++ 17. Чередование операторов в функции между двумя вызовами функций всегда было запрещено, хотя, когда оптимизатор получает ваш код, гарантируется только эффект.
Если вы напишите a() ; b()
, тогда a () будет полностью выполнен, прежде чем b будет полностью выполнен. То же самое, если вы напишите a(), b()
или a() && b()
Если вы напишите a() + b()
, то до c ++ 17 нет гарантии того, что a () будет выполнено до b (), но есть гарантия, что любое из выполненных первым будет полностью завершено до того, как другое будет выполнено. казнены.
Если вы напишите c(a(), b())
, это [насколько я понимаю], опять же, нет никакой гарантии, что a () будет выполнена перед b (), но есть / есть / гарантия того, что результаты первой выполненной функции (в зависимости от того, что то есть) завершится до запуска второго, и, конечно, есть гарантия, что c () не будет выполнена, пока не завершатся оба a () и b ().
Оптимизатор должен соблюдать намерения этой гарантии, хотя он может принимать операторы a () и b () и даже c () и смешивать их, эффект запуска кода должно быть таким же, как если бы они были запущены в последовательности. Может ли код -O0 выполнить a (), а затем b (), а код -O3 выполнить b (), а затем a ()? Возможно, хотя это и затруднит отладку, так что я надеюсь, что нет.
Компилятор должен дать эффект только в конечном результате, и в многопоточности другой поток может наблюдать эффекты последовательных строк кода, происходящих не по порядку, если не используются конкретные конструкции с поддержкой потоков.
Насколько я понимаю, оптимизатор не может допустить, чтобы специфические эффекты a (), b () и c () появлялись не по порядку между каждой функцией, хотя до c ++ 17 порядок a () и b () не определены четко - все эффекты b () могут возникать раньше всех эффектов a ().