Я думаю, що ця частина проекту стандарту щодо порядку оцінки є актуальною:
1.9 Виконання програми
...
- За винятком випадків, коли оцінки операндів окремих операторів та підвиразів окремих виразів не є наслідком. Обчислення значень операндів оператора секвенуються перед обчисленням значення результату оператора. Якщо побічний ефект на скалярний об'єкт не є наслідком щодо іншого побічного ефекту на той самий скалярний об'єкт або обчислення значення, використовуючи значення того ж скалярного об'єкта, і вони потенційно не є одночасним, поведінка не визначена
і також:
5.2.2 Виклик функції
...
- [Примітка: Оцінки експресії постфіксу та аргументів не мають наслідків один щодо одного. Всі побічні ефекти оцінок аргументів простежуються перед введенням функції - кінцева примітка]
Отже, для вашої лінії c.meth1(&nu).meth2(nu);розгляньте, що відбувається в операторі з точки зору оператора виклику функції для остаточного виклику meth2, щоб ми чітко бачили розбиття на вираз та аргумент постфіксу nu:
operator()(c.meth1(&nu).meth2, nu);
В оцінках вираження постфікса і аргумент для виклику функції кінцевого (тобто вираз постфікса c.meth1(&nu).meth2і nu) є unsequenced відносно один одного відповідно до викликом функції правило , вище. Отже, побічний ефект обчислення виразу постфіксу на скалярному об'єкті не arє наслідком щодо оцінки аргументу nuдо meth2виклику функції. За правилом виконання програми вище, це невизначена поведінка.
Іншими словами, для компілятора немає вимоги оцінювати nuаргумент до meth2виклику після meth1виклику - вільний припускати, що жодні побічні ефекти не meth1впливають на nuоцінку.
Код складання, вироблений вище, містить таку послідовність у mainфункції:
- Змінна
nuвиділяється на стек і ініціалізується з 0.
- Реєстр (
ebxу моєму випадку) отримує копію значенняnu
- Адреси
nuта cзавантажуються в регістри параметрів
meth1 це називається
- Регістр значення, що повертається , і раніше кешований значення з
nuв ebxрегістрі завантажуються в регістри параметрів
meth2 це називається
Критично, на етапі 5 вище компілятор дозволяє nuповторно використовувати кешоване значення з кроку 2 у виклику функції до meth2. Тут він нехтує можливістю, яка, nuможливо, була змінена закликом до meth1«невизначеної поведінки» в дії.
ПРИМІТКА. Ця відповідь змінилася по суті від її початкової форми. Моє початкове пояснення щодо побічних ефектів обчислення операндів, які не були секвенсовані перед кінцевим викликом функції, були невірними, оскільки вони є. Проблема полягає в тому, що обчислення самих операндів невизначено послідовно.