Порядок оцінки параметрів функції C ++


90

Якщо у нас є три функції (foo, bar і baz), які складені так ...

foo(bar(), baz())

Чи є якась гарантія стандарту C ++, що бар буде оцінений до базового рівня?

Відповіді:


102

Ні, такої гарантії немає. Це не визначено відповідно до стандарту C ++.

Б'ярн Страуструп також прямо про це говорить у "Мові програмування на C ++", у третьому виданні, розділ 6.2.2, з деякими міркуваннями:

Кращий код може бути сформований за відсутності обмежень щодо порядку оцінки виразів

Хоча технічно це стосується попередньої частини того самого розділу, де сказано, що порядок оцінки частин виразу також не визначений, тобто

int x = f(2) + g(3);   // unspecified whether f() or g() is called first

Я можу прийняти цю відповідь за 8 хвилин ... Мабуть, я трохи зупиняюся!
Clark Gaebel

4
Так, але кращий код міг би бути НАПИСАНИМ (= чистішим), якщо порядок оцінки виразів був СТРОГИМ, що, як правило, набагато важливіше, ніж генерація коду. Дивіться цей приклад: stackoverflow.com/questions/43612592/… Отже, Stroustrup.
Білл Коціас

1
Якщо замовлення має значення, ви можете самостійно провести секвенування. Якщо вчинити інакше, це завжди призведе до витрат на те, що не завжди (рідко?) Має значення. Я думаю, що політика не платити за те, що ви не використовуєте, є єдиним, з чим погоджуються більшість програмістів на C ++.
tweej,

3
Чи це не має бути "невизначена поведінка" замість "невизначена"?
GoodDeeds

1
@ChrisDodd, проголосувавши за прийняту відповідь через використання слова "невизначений" проти "невизначений", для мене відчувається як зловмисний педантизм ... Я не сказав, що це "невизначена поведінка", а в іншому випадку "невизначені" та "невизначені" здаються синонімом? У будь-якому випадку, пропонування редагування відповіді було б більш продуктивним способом обговорити це
Елі Бендерський

20

Немає вказаного порядку для bar () і baz () - єдине, що каже Стандарт, це те, що вони обидва будуть оцінені до виклику foo (). Зі стандарту C ++, розділ 5.2.2 / 8:

Порядок оцінки аргументів не визначений.


4
Той факт, що їх оцінюють перед foo (), принаймні трохи заспокоює.
Білл Коціас

1
@BillKotsias Стандарт також говорить, що виклики функцій не можуть перекриватися (тобто реалізація не може запускати рядок 1 bar, потім рядок 1 baz, потім рядок 2 barтощо), що також приємно. :-)
Melpomene

20

З [5.2.2] виклику функції,

Порядок оцінки аргументів не визначений. Усі побічні ефекти обчислення виразів аргументів набувають чинності до введення функції.

Отже, немає жодної гарантії, яка bar()діятиме раніше baz(), лише ця bar()і baz()буде викликана раніше foo.

Також зверніть увагу на [5] вирази, що:

за винятком випадків, коли зазначено [наприклад, спеціальні правила для &&та ||], порядок оцінки операндів окремих операторів та підвираження окремих виразів, а також порядок, у якому мають місце побічні ефекти, не визначено.

так що навіть якщо ви питали чи bar()буде працювати , перш ніж baz()в foo(bar() + baz())порядок до сих пір НЕ визначено.


4
Приклад "спеціальної примітки" з [5.14] Логічний оператор І: "На відміну від &, &&гарантує оцінку зліва направо: другий операнд не обчислюється, якщо перший операнд false".
Даніель Требб'єн,


2

У C ++ 11 відповідний текст можна знайти в 8.3.6 Аргументи за замовчуванням / 9 (Підкреслити мій)

Аргументи за замовчуванням обчислюються кожного разу, коли викликається функція. Порядок оцінки аргументів функції не визначений . Отже, параметри функції не повинні використовуватися в аргументі за замовчуванням, навіть якщо вони не обчислюються.

Те саме словосполучення також використовується стандартом C ++ 14, і воно знаходиться в тому ж розділі .


0

Як вже зазначали інші, стандарт не дає жодних вказівок щодо порядку оцінки для цього конкретного сценарію. Потім такий порядок оцінки залишається компілятору, і компілятор може мати гарантію.

Важливо пам’ятати, що стандарт С ++ - це справді мова, яка дає інструкції компілятору щодо побудови збірки / машинного коду. Стандарт - це лише одна частина рівняння. Там, де стандарт неоднозначний або конкретно реалізований, слід звернутися до компілятора та зрозуміти, як він перекладає інструкції C ++ на справжню машинну мову.

Отже, якщо порядок оцінки є вимогою або принаймні важливим, а сумісність між компіляторами не є вимогою, дослідьте, як ваш компілятор в кінцевому підсумку складе це разом, ваша відповідь може лежати там. Зверніть увагу, що компілятор може змінити свою методологію в майбутньому

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.