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

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

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

vs

value += increment;

if (value > valueMax)
    value = valueMax;

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

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

3 ответов


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

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

64-битный лязг:

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

на VC10 при выпуске для следующего кода у нас есть следующая сборка:

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 заявление. Он оптимизирован и более удобочитаем.


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