В 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::, и тогда вторая версия может быть потенциально быстрее, поскольку назначение условно.