如何寫優雅的代碼(1)——靈活使用goto和__try

//========================================================================
//TITLE:
//    如何寫優雅的代碼(1)——靈活使用goto和__try
//AUTHOR:
//    norains
//DATE:
//    Thursday  16-July-2009
//Environment:
//    WINCE5.0 + VS2005
//========================================================================

    goto是毒藥?凡是能用goto的地方,肯定能用結構化方式來實現相同的目的!估計很多朋友都對這論斷不會陌生,甚至可以說,太熟悉了!但能實現並不代表優雅。不信?我們接下來看看。
   
    假設我們有一個函數,需要實現如下功能:將一個驅動某些內容讀取到緩存區去;又因爲該緩存是全局公用的,所以我們很自然採用互斥量來進行控制。首先,我們堅持採用結構化方式實現,很可能我們的代碼類似如下:

 

    沒錯,採用這種結構化的方式的確是解決了問題。可是,我們是不是有點彆扭呢?每次出錯,返回FALSE之前,都必須要清理一次資源。小函數也許還不是什麼大問題,只要睜大眼睛,小心翼翼,還是能在後續的返回中正確處理資源釋放的。但如果函數因爲要加入某些功能越來越大,又或許是別人來維護這段代碼,那能保證在返回前釋放資源麼?
 
 
    接下來我們使用被大家鄙棄的goto,看看會發生什麼情形:

 

    怎麼樣?把所有的資源釋放都放到EXIT段中,每個EnterCriticalSection都能對應一個LeaveCriticalSection,是不是顯得比之前的更爲優雅?還能說goto爲雞肋麼?
   
    不過,goto也不是盡善盡美,比如變量dwSize在goto之後就不能初始化,只能將局部變量的初始化放到第一個goto之前。按照C++的建議,變量的聲明最好儘可能接近使用的地方。而放在第一個goto之前,擺明就是C作風嘛!
   
    其實如果以本特例,直接聲明dwSize而不進行初始化也是可行的;但這並不代表在別的情況下也能暢通無阻,也許有的程序就依賴於初始化的值,誰知道呢?
   
   
    那有沒有更爲優雅的?可以解決這dwSize的位置問題的?答案自然是肯定的。不過,就必須請我們的__try出場咯:

 

    哦耶!現在dwSize終於在它該出現的位置上了,是不是顯得比goto更爲優雅呢?
   
    這段改寫的代碼採用的是SEH機制。因爲SEH機制如果需要詳細解釋,就不是一言兩語的事情,所以在此就略過,感興趣的朋友可以自己在網上查找資料。在這裏,只是說明一點,採用SEH機制,無論如何,最後基本上一定要運行__finally段代碼,除非中間有中斷。
   
   
    最後一段是不是意味着凡是可以運用goto的地方都能採用__try替代?答案是否定的。特別是代碼中採用了STL,SEH機制將會無能爲力。
   
    不信?我們添加一點代碼段來看看事情的真相。假設我們不是通過數組來保留緩存,而是保留於STL的vector中,並且成功讀取之後,我們還想輸出每個數值,那麼我們代碼可以如下:

 


    很遺憾,這段代碼無法編譯通過。因爲STL的迭代器中用到了對象,而對象會釋放C++異常,而這和SEH有衝突。當然,我們完全可以用new來替代,以避開這個問題,但這樣一來,卻是使代碼更崢嶸,離優雅更是八輩子打不到一個杆子上。
   
    這時候,還是隻能用goto:

 

    最後這個例子,從另一個角度說明了,goto並不一定是雞肋,在某些特定的環境下,只有它才能拯救代碼於優雅之境地。
   

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章