В С++ лучше ли ограничить значение с помощью std:: min или ветки if? - программирование

В С++ лучше ли ограничить значение с помощью std:: min или ветки if?

Очень распространенный шаблон в программировании - это ограничение максимального значения после некоторого обновления. Я хотел бы знать, есть ли разница между двумя этими двумя частями кода, и если вам нужно быть предпочтительным:

value += increment;
value = std::min(value, valueMax);

против

value += increment;

if (value > valueMax)
    value = valueMax;

Мое мышление заключается в том, что это сводится к тому, что у процессоров есть инструкции для принятия двух значений и получения минимальной суммы. Если это так, вызов std:: min должен привести к этой инструкции и избежать ненужной ветки. Если нет, вторая версия избегает ненужного присваивания, когда значение <= значениеMax.

Я не очень хорошо разбираюсь в подобных вещах, но я уверен, что там есть хакеры из старой школы, которые это узнают. Им я спрашиваю: что лучше?

4b9b3361

Ответ 1

Современные компиляторы достаточно умны, чтобы генерировать один и тот же код в обоих случаях. Например, 32-разрядный GCC генерирует:

addl    %esi, %edi
cmpl    %edx, %edi
movl    %edi, %eax
cmovgl  %edx, %eax

64-бит Clang:

%1 = add nsw i32 %increment, %value
%2 = icmp sgt i32 %1, %valueMax
%value = select i1 %2, i32 %valueMax, i32 %1

Ответ 2

В VC10 on Release для следующего кода мы имеем следующую сборку:

int main(int argc, char *argv[])
{ 
  int dummyValue = 0, valueMax = 3000, value = valueMax + 1;

  cin >> valueMax;
  cin >> value;

  dummyValue = std::min(value, valueMax);

  cout << dummyValue;
  cin >> valueMax;
  cin >> value;

  if (value > valueMax)
    dummyValue = valueMax;

  cout << dummyValue;
  return 0;
}

Сформирован:

  24:   dummyValue = std::min(value, valueMax);
00E112AF  mov         eax,dword ptr [valueMax]  
00E112B2  cmp         eax,dword ptr [value]  
00E112B5  lea         edx,[value]  
00E112B8  lea         ecx,[valueMax]  
00E112BB  cmovge      ecx,edx     // <-- this is our conditional assignment
00E112BE  mov         esi,dword ptr [ecx]  

и

if (value > valueMax)
  dummyValue = valueMax
00E112ED  mov         eax,dword ptr [valueMax]  
00E112F0  cmp         dword ptr [value],eax  
00E112F3  mov         ecx,dword ptr ds:[0E13038h]  
00E112F9  cmovg       esi,eax  

Таким образом, оба случая оптимизированы для cmovge или cmovg.

Я все равно поеду с std::min, потому что он показывает намерение лучше, чем оператор if. Он оптимизировался и стал более читаемым.

Ответ 3

Ответ зависит от типа значения. Код может быть эффективно оптимизирован, если все операции полностью прозрачны для оптимизатора кода, что будет иметь место, если значение является простым целым числом. Но ваш код также будет компилироваться, если значение равно std::string, а затем вторая версия может быть потенциально быстрее, поскольку назначение условно.