在C ++中,最好使用std :: min或if分支来限制值吗?

问题描述 投票:16回答:4

编程中非常常见的模式是在进行某种更新后将值限制为最大值。我想知道的是,以下两段代码之间是否有区别,以及是否应优先使用:

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

vs

value += increment;

if (value > valueMax)
    value = valueMax;

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

时避免不必要的分配

我对这种事情不太满意,但是我敢肯定,有一些老式的汇编黑客会知道这一点。我问他们:哪个更好?

c++ cpu minimum instruction-set
4个回答
11
投票

现代编译器足够聪明,可以在两种情况下生成相同的代码。例如,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

4
投票

在以下代码的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  

所以两种情况都优化为cmovgecmovge指令。

我仍然会选择cmovg,因为它显示的意图比cmovg语句更好。它经过优化,更具可读性。


0
投票

答案取决于值的类型。如果所有操作对代码优化器都是完全透明的,则可以有效地优化代码,如果value是纯整数,情况就是这样。但是,如果value是std :: string,您的代码也将编译,然后第二个版本可能会更快,因为赋值是有条件的。]


0
投票

这通常应该比分支要快得多:

© www.soinside.com 2019 - 2024. All rights reserved.