if语句在循环中的潜在影响

时间:2016-12-25 10:15:59

标签: c#

假设我们有template <typename R, typename T0, typename T1> using ResType = std::conditional_t< std::is_same<void, R>::value, std::common_type_t<T0, T1>, // default R // R was explicitly specified: use it >; template <typename R = void, typename T0, typename T1> ResType<R, T0, T1> add(T0 a, T1 b) { return static_cast<ResType<R, T0, T1>>(a + b); } ,并且此变量的值总是为true或false,这意味着它永远不会通过循环更改,下面的计算效率是否会高于后者?

首先:

char a = 1, b = 2;
add(a, b);       // returns char
add<int>(a, b);  // returns int

第二:

Boolean check = false

4 个答案:

答案 0 :(得分:5)

对此没有一般性的答案,特别是在现代CPU上。

理论上

从理论上讲,代码中的分支越少越好。因此,由于第二个语句在每次循环迭代时重复一次分支,因此需要更多的处理时间,因此效率较低。

在实践中

现代CPU执行所谓的分支预测。这意味着他们试图提前弄清楚是否有分支机构。如果预测是正确的,那么分支是空闲的(在0个CPU周期中是空闲的),如果它不正确,则CPU必须刷新其执行队列并且分支非常昂贵(如很多更多超过1个CPU周期。)

在您的具体示例中,您有两种分支类型,即循环的类型和if的分支类型。由于if的条件没有改变且循环具有固定数量的执行,因此两个分支对于分支预测引擎的预测都是微不足道的,并且您可以期望两个选项都执行相同的操作。

在编码练习中

性能考虑很少在实践中产生影响(特别是在这种情况下,因为分支预测),因此您应该选择更好的编码风格。我会考虑在这方面做出更好的第二种选择。

答案 1 :(得分:3)

此外,整个代码可以重构为:

Func<int, string> getText;

if(array.Length > 2) getText = i => $@"A - ""{array[i]}""";
else getText = i => $@"B - ""{array[i]}""";

for(int i = 0; i < array.Length; i++) sb.Append(getText(i));

也就是说,你基于一些布尔检查来定义整个Func<int, string>,然后你针对预定义的for执行整个Func<int, string>循环,这不需要检查再也没有了,你也不要重复自己!

看看我是如何使用插值字符串的,这是常规字符串连接的语法糖,我使用逐字符串来使用 double quots 来转义求值。

总结:

  • 你不要重复自己。
  • 您可以避免多次拨打string.Format
  • 您可以避免多次拨打string.ToString()
  • 减少代码行。
  • 编译代码更简单,因为委托最终调用生成的内部类中的方法,其余操作只是常规字符串连接的语法糖...

我知道......

我知道我的答案根本没有解决这个问题,但是我想给OP一些关于如何从高层次角度优化代码的提示,而不是关注低级细节。

答案 2 :(得分:2)

Sefe的回答非常有趣,但如果你事先知道整个循环中的值不会改变,那么你真的不应该在循环中进行检查。

最好将决定与循环完全分开:

height

答案 3 :(得分:-1)

第一个更有效率。但编译器优化可能会在编译期间解决后一种情况。