Якщо у нас є три функції (foo, bar і baz), які складені так ...
foo(bar(), baz())
Чи є якась гарантія стандарту C ++, що бар буде оцінений до базового рівня?
Якщо у нас є три функції (foo, bar і baz), які складені так ...
foo(bar(), baz())
Чи є якась гарантія стандарту C ++, що бар буде оцінений до базового рівня?
Відповіді:
Ні, такої гарантії немає. Це не визначено відповідно до стандарту C ++.
Б'ярн Страуструп також прямо про це говорить у "Мові програмування на C ++", у третьому виданні, розділ 6.2.2, з деякими міркуваннями:
Кращий код може бути сформований за відсутності обмежень щодо порядку оцінки виразів
Хоча технічно це стосується попередньої частини того самого розділу, де сказано, що порядок оцінки частин виразу також не визначений, тобто
int x = f(2) + g(3); // unspecified whether f() or g() is called first
Немає вказаного порядку для bar () і baz () - єдине, що каже Стандарт, це те, що вони обидва будуть оцінені до виклику foo (). Зі стандарту C ++, розділ 5.2.2 / 8:
Порядок оцінки аргументів не визначений.
bar
, потім рядок 1 baz
, потім рядок 2 bar
тощо), що також приємно. :-)
З [5.2.2] виклику функції,
Порядок оцінки аргументів не визначений. Усі побічні ефекти обчислення виразів аргументів набувають чинності до введення функції.
Отже, немає жодної гарантії, яка bar()
діятиме раніше baz()
, лише ця bar()
і baz()
буде викликана раніше foo
.
Також зверніть увагу на [5] вирази, що:
за винятком випадків, коли зазначено [наприклад, спеціальні правила для
&&
та||
], порядок оцінки операндів окремих операторів та підвираження окремих виразів, а також порядок, у якому мають місце побічні ефекти, не визначено.
так що навіть якщо ви питали чи bar()
буде працювати , перш ніж baz()
в foo(bar() + baz())
порядок до сих пір НЕ визначено.
&
, &&
гарантує оцінку зліва направо: другий операнд не обчислюється, якщо перший операнд false
".
C ++ 17 визначає порядок оцінки для операторів, який не був визначений до C ++ 17. Дивіться запитання Які гарантії замовлення на оцінку запроваджує C ++ 17? Але зверніть увагу на свій вираз
foo(bar(), baz())
ще не вказав порядок оцінки.
У C ++ 11 відповідний текст можна знайти в 8.3.6 Аргументи за замовчуванням / 9 (Підкреслити мій)
Аргументи за замовчуванням обчислюються кожного разу, коли викликається функція. Порядок оцінки аргументів функції не визначений . Отже, параметри функції не повинні використовуватися в аргументі за замовчуванням, навіть якщо вони не обчислюються.
Те саме словосполучення також використовується стандартом C ++ 14, і воно знаходиться в тому ж розділі .
Як вже зазначали інші, стандарт не дає жодних вказівок щодо порядку оцінки для цього конкретного сценарію. Потім такий порядок оцінки залишається компілятору, і компілятор може мати гарантію.
Важливо пам’ятати, що стандарт С ++ - це справді мова, яка дає інструкції компілятору щодо побудови збірки / машинного коду. Стандарт - це лише одна частина рівняння. Там, де стандарт неоднозначний або конкретно реалізований, слід звернутися до компілятора та зрозуміти, як він перекладає інструкції C ++ на справжню машинну мову.
Отже, якщо порядок оцінки є вимогою або принаймні важливим, а сумісність між компіляторами не є вимогою, дослідьте, як ваш компілятор в кінцевому підсумку складе це разом, ваша відповідь може лежати там. Зверніть увагу, що компілятор може змінити свою методологію в майбутньому