假设我们有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
答案 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)
第一个更有效率。但编译器优化可能会在编译期间解决后一种情况。