2012-02-23 206 views
0

考慮下面的功能如何避免重複

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

回答

2

您可以通過模板參數傳遞功能:

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

6

你可以嘗試做這樣的功能模板接受一個任意斷言。如果謂詞很簡單,就像在你的情況下一樣,你可以依靠編譯器來內聯它,所以不會有效率的損失。你應該分析你的應用程序來驗證。代碼看起來是這樣的:

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