Защо редът на оценка за функционални параметри не е посочен в c++?

Стандартът не определя реда на оценка на аргументите с този ред:

Редът на оценяване на аргументите не е уточнен.

Какво прави

По-добър код може да бъде генериран при липса на ограничения за реда на оценка на израза

предполагат?

Какъв е недостатъкът да поискате от всички компилатори да оценят аргументите на функцията отляво надясно например? Какви видове оптимизации извършват компилаторите поради тази неуточнена спецификация?


person unj2    schedule 22.09.2012    source източник
comment
Разрешаването на компилатора да пренареди оценката на операндите добавя повече място за оптимизация.   -  person Mysticial    schedule 22.09.2012
comment
@Mysticial: Колкото и абсурдно да изглежда, това трябва да е отговор и всъщност приетият отговор!   -  person David Rodríguez - dribeas    schedule 22.09.2012
comment
Какви видове оптимизации извършват компилаторите?   -  person unj2    schedule 22.09.2012
comment
Ако се сетя за пример, ще го направя отговор.   -  person Mysticial    schedule 22.09.2012
comment
Някои конвенции за извикване предават параметри отдясно наляво. Други минават отляво надясно. Понякога е по-ефективно да се оценява в същия ред, в който са изпратени.   -  person Raymond Chen    schedule 22.09.2012


Отговори (2)


Разрешаването на компилатора да пренареди оценката на операндите добавя повече място за оптимизация.

Ето един напълно измислен пример за илюстрация.

Да предположим, че процесорът може:

  • Издайте 1 инструкция на всеки цикъл.
  • Изпълнете добавяне в 1 цикъл.
  • Изпълнете умножение в 3 цикъла.
  • Може да изпълнява събирания и умножения едновременно.

Сега да предположим, че имате извикване на функция, както следва:

foo(a += 1, b += 2, c += 3, d *= 10);

Ако трябваше да изпълните това отляво надясно на процесор без OOE:

Cycle - Operation
0     -    a += 1
1     -    b += 2
2     -    c += 3
3     -    d *= 10
4     -    d *= 10
5     -    d *= 10

Сега, ако позволите на компилатора да ги пренареди: (и първо започнете умножението)

Cycle - Operation
0     -    d *= 10
1     -    a += 1, d *= 10
2     -    b += 2, d *= 10
3     -    c += 3

Така че 6 цикъла срещу 4 цикъла.

Отново това е напълно измислено. Съвременните процесори са много по-сложни от това. Но разбирате идеята.

person Mysticial    schedule 22.09.2012

Ето един прост пример. Да предположим, че имате извикване на функция, както следва:

// assume that p is a pointer to an integer
foo(*p * 3, bar(), *p * 3 + 1);

Компилаторът трябва да дереферира p два пъти (и да направи някои изчисления въз основа на резултата) и да извика bar веднъж. Ако компилаторът е умен, може да пренареди оценката на

int temp = *p * 3;
foo(temp, bar(), temp + 1);

По този начин трябва да направи "дереференция, умножение по 3" само веднъж. Това е известно като елиминиране на общ подизраз.

person Raymond Chen    schedule 24.09.2012
comment
Честно казано, дори езици, които гарантират ред на оценка, могат да направят това, при условие че могат да докажат, че стойността на p не може да се промени между тях. Разбира се, с модела на паметта C това е почти невъзможно да се гарантира, което вероятно е причината да е необходим недефиниран ред на оценка, за да се постигне тази оптимизация. - person Joey; 27.09.2012