由C++的異常處理聯想到RAII

來源:互聯網
上載者:User

    在傳統的C語言,我們通過檢查函數的傳回值以判斷調用是否成功,並處理各類異常情況,在Unix環境下可以通過設定error變數發出錯誤訊息,並通過setjmp, longjmp來跳出深層次調用。C++語言在此基礎上引入了Exception機制,遇到異常的程式模組可以throw一個異常,其他方法可以通過try catch來捕捉該異常。但是相比後來的Java與C#中的異常處理機制,C++的還是有不少待完善的地方:

1,缺少Exception基類,任何類都可以作為作為異常被拋出,且可以拋出對象,引用或者指標。

2,沒有像Java那樣約束方法,強制要求其處理或者拋出其內部所有可能發生的異常。比如:調用該方法的其他程式模組根本無法從介面中判斷其是否會拋出異常,也就不會注意處理其異常。

正因為這樣,造成C++程式員很少會使用其異常機制,我通常還是按照C語言的方式,利用傳回值來區分各類錯誤,有時候偶爾在類的建構函式中會使用異常,因為在建構函式中產生的錯誤可能會造成產生的對象不正常,而建構函式沒有傳回值,因此只能拋出異常,或者設定一個狀態標誌位。

此外C++中異常機制的一大弊端就是會造成資源泄漏,比如:

void f()

{

    Resource * r = new Resource();

    FILE * f = fopen(“datafile.txt”);

    DoSomething();  //這裡可能會拋出異常,造成後面的代碼無法執行,資源得不到及時釋放。

    delete r;

    fclose(f);  

}

為瞭解決資源泄漏的問題,當然不僅僅是因為異常引起的,還有可能是在程式編寫過程中,某些地方不小心直接return了,或者為了避免在每一個返回語句前都加上一段delete, fclose之類的語句。在此我們需要用的C++的RAII機制:

RAII: Resource Acqusition is Initialization資源申請即初始化

其利用的原理就是堆棧上的對象在離開範圍時均會被自動調用解構函式,因此我們可以在建構函式中直接申請資源,在解構函式中釋放資源,從而保證資源始終能夠得到正常釋放。

比如:

class File

{

public:

    File(const char * file_name) { f = fopen(file_name); ….}

    ~File() {fclose(f);}

    int write(const char *data, int len);

    int read(char *data, int len);

private:

    FILE *f;

}

另外std::auto_ptr也是基於這個原理構造的。

還有一點要提出的是,有些人喜歡在建構函式中將資源初始化為空白,單獨使用其他的方法來申請資源,比如在上述File的建構函式中令f=NULL,再添加一個open()方法來開啟檔案,我個人認為這是沒有必要的,因為如果這樣的話,那麼在write與read方法中肯定每次都需要判斷f是否不為NULL。具體的應用見仁見智,因此在C#與Java中貌似很多都有預設什麼都不乾的建構函式。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.