在C++中,使用std :: min或if分支限制值是否更好?

vol*_*evo 16 c++ cpu instruction-set minimum

编程中一种非常常见的模式是在某种更新后将值限制在最大值.我想知道的是,如果以下两段代码之间存在差异,并且是否应该首选:

value += increment;
value = std::min(value, valueMax);
Run Code Online (Sandbox Code Playgroud)

VS

value += increment;

if (value > valueMax)
    value = valueMax;
Run Code Online (Sandbox Code Playgroud)

我的想法是,这取决于CPU是否有获取两个值并产生最小值的指令.如果是这样,对std :: min的调用应该导致该指令并避免不必要的分支.如果不是,则第二个版本在值<= valueMax时避免不必要的赋值.

我对这种事情不是很了解,但我确信有老派的黑客大佬会知道这一点.我问他们:哪个更好?

gre*_*rep 11

现代编译器非常智能,可以在两种情况下生成相同的代码.例如,32位GCC生成:

addl    %esi, %edi
cmpl    %edx, %edi
movl    %edi, %eax
cmovgl  %edx, %eax
Run Code Online (Sandbox Code Playgroud)

64位Clang:

%1 = add nsw i32 %increment, %value
%2 = icmp sgt i32 %1, %valueMax
%value = select i1 %2, i32 %valueMax, i32 %1
Run Code Online (Sandbox Code Playgroud)

  • @ Mozza314这里没有分店.编译器做得尽可能好 - 这是使用条件移动. (2认同)

Ed *_*rbu 6

在 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;
}
Run Code Online (Sandbox Code Playgroud)

生成:

  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]  
Run Code Online (Sandbox Code Playgroud)

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  
Run Code Online (Sandbox Code Playgroud)

因此这两种情况都针对cmovgeorcmovg指令进行了优化。

我仍然会同意,std::min因为它比if声明更能显示意图。它已经过优化并且更具可读性。