如何避免重复
考虑下面的功能如何避免重复
f(int a[])
{
///CODE
for
for
if(a[i] > 0)
//change i on some condition
for
//CODE
if(a[i] > 0)
///CODE
}
f(int a[], int th)
{
///CODE
for
for
if(a[i] < th)
//change i on some condition
for
//CODE
if(a[i] < th)
///CODE
}
所以我们F的功能与优化庞大的身躯, 几行是一样的:如果(A [1]> 0) 我要添加扩展这个函数使得如果添加了一个参数,这些行应该改为if(a [i] < th) 当我重载函数时,数百行会被复制(变得很难维护),所以我不想要这个。此外,我不能将身体划分为功能,因为“线条”出现在太多的内部循环中。
第一个想法:
f(int a[], int th = -1)
{
///CODE
if(th == -1)
if(a[i] > 0)...
else
if(a[i] < th)...
///CODE
}
我不能这样做,因为引入额外的,如果到内循环的性能开销。 有没有一种方法可以有效和清晰地解决它,也许使用模板或宏?
您可以通过模板参数传递功能:
template<bool Cmp(int,int)>
void f(int a[], int th)
{
//..
if (Cmp(a[i],th)) {
//...
}
//...
}
然后,您可以使用f
这样的:
bool cmp(int a, int b) { return a < b; }
f<cmp>(...)
重要的是,函数应该由编译器内联。 – 2012-02-23 10:46:13
@OliCharlesworth:啊,是的,这就是为什么我避免了stl的“少”功能。它更复杂(作为仿函数来实现),你无法确定它是否被内联。尽管对于每个使用的编译器来说,最好检查汇编。但通常它工作得很好。如果不是,你可以使用'inline'关键字或甚至一些编译器特定的属性。 – Florian 2012-02-23 10:51:15
@ krynr:谢谢,它工作!看起来,当我们将函数作为模板参数传递时,编译器可以将它们内联。 – 2012-02-24 09:10:24
你可以尝试做这样的功能模板接受一个任意断言。如果谓词很简单,就像在你的情况下一样,你可以依靠编译器来内联它,所以不会有效率的损失。你应该分析你的应用程序来验证。代码看起来是这样的:
template<class Pred>
void f(int a[], Pred pred) {
///CODE
for
for
if(pred(a[i]))
//change i on some condition
for
//CODE
if(pred(a[i]))
///CODE
}
预C++ 11你必须通过仿函数或函数指针谓语,在C++ 11你可以使用lambda表达式:
f(data, [](int val){ return val > 0; });
f(data, [th](int val){ return val < th; });
我喜欢这个解决方案。如果整个函数的主体很大,我会说要减少它,分解到外部循环部分发生,因此,主要只有需要模板化的部分是。 – CashCow 2012-02-23 11:08:55
函数指针似乎是一个很好的尝试......? – CppLearner 2012-02-23 10:40:28
@CppLearner:由于性能限制,无法做到这一点。内循环内部不允许进行函数调用。 – 2012-02-23 10:41:54
在大多数现代CPU上,正确预测并且不需要计算的'if'基本上是免费的。您是否猜测“引入额外的性能开销”或者您是否测量过?保持代码简单,编译器将优化它。 – 2012-02-23 10:47:43