2012-07-07 111 views
7

看着一些舊的代碼,我們有很多事情像下面這樣:讀取原語時,stringstream是否可以引發異常?

// This is dumb 
string do_something(int in) 
{ 
    stringstream out; 
    try 
    { 
     out << std::fixed << in; 
    } 
    catch(std::exception &e) 
    { 
     out << e.what(); 
    } 

    return out.str(); 
} 

// Can't we just do this? Can this ever fail? 
string do_something_better(int in) 
{ 
    stringstream out; 
    out << std::fixed << in; 
    return out.str(); 
} 

當一個字符串流讀取原始它可以不斷拋出一個異常?閱讀字符串時怎麼辦?

+11

該代碼是瘋了。你捕捉由流引發的錯誤,然後使用相同的** **流,試圖傳達錯誤。更糟的是,你亂拋垃圾的低級別的代碼完全沒有意義的異常處理,這無助於恢復* *從錯誤中,留在流中處於中斷狀態。你應該在一個水平,你可以做* *關於他們的東西被抓住這些錯誤,即使它只是提醒用戶,並中止程序。這是對異常處理的完全濫用。 – meagar 2012-07-07 21:14:45

+0

它可以拋出異常,但前提是你通過調用'out.exceptions(selected_exceptions)'來啓用它們。默認構造流不拋出異常(除'bad_alloc',你也很難處理這裏)。 – 2012-07-07 21:21:50

+0

你完全可以處理'bad_alloc'。只需釋放一堆內存。 – 2012-07-07 21:32:24

回答

7

總結幾個答案

默認情況下,流不會拋出異常。他們可以,如果他們被啓用。

stringstream out; 
out.exceptions(std::ios::failbit); // throw exception if failbit gets set 

按照 Apache C++ Standard Library User's Guide

國旗的std ::的ios_base :: badbit指示與基礎流緩衝器的問題。這些問題可能是:

內存不足。沒有可用於創建緩衝區的內存,或者由於其他原因(例如從流外部提供)而使緩衝區大小爲0,或者流無法爲其內部數據分配內存,就像使用std :: ios_base :: iword()和std :: ios_base :: pword()。

基礎流緩衝區引發異常。流緩衝區可能會失去其完整性,如內存不足,代碼轉換失敗或外部設備發生不可恢復的讀取錯誤。流緩衝區可以通過拋出異常來指示完整性的丟失,該異常由流捕獲並導致將badbit設置爲流的狀態。

通常,您應該記住,badbit表示可能無法恢復的錯誤情況,而failbit表示可能允許您重試失敗操作的情況。

因此它似乎是最安全的方式做這將是

string do_something(int in) 
{ 
    stringstream out; // This could throw a bad_alloc 
    out << std::fixed << in; // This could set bad or fail bits 

    if(out.good()) 
    { 
     return out.str(); 
    } 
    else 
    { 
     return ""; 
    } 
} 

這是矯枉過正,但因爲根據Handling bad_alloc如果在創建流失敗,也有更大的問題擔心,程序可能會退出。因此,假設它通過創建流,這是可能的,但不太可能的badbit被設置。 (流獲取分配內存< sizeof(int))。

故障位也不太可能被設置(不確定用於讀取堆棧而不是損壞堆棧的用例)。所以下面的代碼就足夠了,因爲在這一點上從流錯誤恢復是不可靠的。

string do_something(int in) 
{ 
    stringstream out; 
    out << std::fixed << in; 
    return out.str(); 
} 
2

所有的數據流,包括istringstreams,都可以在讀取時拋出異常(可以用ios::exceptions控制),例如。當他們用完輸入。另外它們可以在內存不足時拋出(例如,在構造當前讀取的字符串時)。

但是,您的代碼示例執行寫入(?)AFAIK寫入,除了明顯的內存不足錯誤(您的代碼無法很好地處理)之外,不應該產生任何異常。