编程中非常常见的模式是在进行某种更新后将值限制为最大值。我想知道的是,以下两段代码之间是否有区别,以及是否应优先使用:
value += increment;
value = std::min(value, valueMax);
vs
value += increment;
if (value > valueMax)
value = valueMax;
我的想法是,这取决于CPU是否具有用于获取两个值并产生最小值的指令。如果是这样,则对std :: min的调用应产生此指令,并避免不必要的分支。如果不是,则第二个版本会在值<= valueMax。
时避免不必要的分配我对这种事情不太满意,但是我敢肯定,有一些老式的汇编黑客会知道这一点。我问他们:哪个更好?
现代编译器足够聪明,可以在两种情况下生成相同的代码。例如,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
在以下代码的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
或cmovge
指令。
我仍然会选择cmovg
,因为它显示的意图比cmovg
语句更好。它经过优化,更具可读性。
答案取决于值的类型。如果所有操作对代码优化器都是完全透明的,则可以有效地优化代码,如果value是纯整数,情况就是这样。但是,如果value是std :: string,您的代码也将编译,然后第二个版本可能会更快,因为赋值是有条件的。]
这通常应该比分支要快得多: