如何避免重复

问题描述:

考虑下面的功能如何避免重复

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 
} 

我不能这样做,因为引入额外的,如果到内循环的性能开销。 有没有一种方法可以有效和清晰地解决它,也许使用模板或宏?

+0

函数指针似乎是一个很好的尝试......? – CppLearner 2012-02-23 10:40:28

+0

@CppLearner:由于性能限制,无法做到这一点。内循环内部不允许进行函数调用。 – 2012-02-23 10:41:54

+2

在大多数现代CPU上,正确预测并且不需要计算的'if'基本上是免费的。您是否猜测“引入额外的性能开销”或者您是否测量过?保持代码简单,编译器将优化它。 – 2012-02-23 10:47:43

您可以通过模板参数传递功能:

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>(...) 
+0

重要的是,函数应该由编译器内联。 – 2012-02-23 10:46:13

+0

@OliCharlesworth:啊,是的,这就是为什么我避免了stl的“少”功能。它更复杂(作为仿函数来实现),你无法确定它是否被内联。尽管对于每个使用的编译器来说,最好检查汇编。但通常它工作得很好。如果不是,你可以使用'inline'关键字或甚至一些编译器特定的属性。 – Florian 2012-02-23 10:51:15

+0

@ 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; }); 
+0

我喜欢这个解决方案。如果整个函数的主体很大,我会说要减少它,分解到外部循环部分发生,因此,主要只有需要模板化的部分是。 – CashCow 2012-02-23 11:08:55