2016-09-09 50 views
2

我想創建一個方法,告訴我如果異常是否可以重試。例外情況來自第三方庫。所以我有這樣的事情:長列表捕獲的性能影響C++

bool isRetryable (std::exception_ptr ex) { 
    try { 
     if(ex) { 
      std::rethrow_exception (ex); 
     } 
     return true; 
    } catch (const ExceptionA& ex) { 
     return true; 
    } catch (const ExceptionB& ex) { 
     return true; 
    } catch (const ExceptionC& ex) { 
     return true; 
    } catch (const ExceptionD& ex) { 
     return false; 
    } catch (const ExceptionE& ex) { 
     return false; 
    } catch (const ExceptionF& ex) { 
     return false; 
    } 
} 

例外列表可以去,只要100,所以我的問題是 - 什麼是例外一長串的影響,並沒有任何其他的方式來完成相同的目標?

+0

我的意思是你可以嘗試測量自己。如果例外有一個共同的基礎,你可以嘗試dynamic_casts:但如果他們更快,你必須測量。 – Hayt

回答

3

這取決於C++運行庫,但一般具有將導致O(n)性能catch塊一長串作爲實現進行線性掃描,針對每個在所述類型的匹配拋出的異常類型反過來抓住塊的列表;這是例如如何libstdC++(Linux上的默認C++運行時)工作。

我不知道是否有其他運行時庫優化了這一點,但我懷疑它們不會,因爲一長串異常塊通常會被視爲「代碼異味」,並且因爲需要實現以確保第一個匹配的catch塊接收異常,這使線性掃描成爲自然實現。

但是,如果所有的異常,由於多態的基礎派生(如std::exception)有一個更優雅的解決方案:你可以採取異常的typeid,構建一個std::type_index,並在容器看看它:

struct ExceptionA : std::exception {}; 
// etc. 

static std::unordered_set<std::type_index> const retryables{ 
    typeid(ExceptionA), 
    typeid(ExceptionB), 
    typeid(ExceptionC) 
}; 

bool isRetryable (std::exception_ptr ex) { 
    try { 
     if(ex) { 
      std::rethrow_exception (ex); 
     } 
     return true; 
    } catch (const std::exception& ex) { 
     return retryables.count(typeid(ex)); 
    } 
} 

Example

+2

很好的答案,但也許仍然指出有100個例外,並在一個地方抓住他們的想法可能表明設計問題 – stijn