Effective C 學習筆記 《十七》

2021-09-23 17:16:56 字數 1599 閱讀 5285

其實這一點講的要點比較隱晦,在平時程式設計的時候很難發現這個問題,但要是不注意卻又是乙個隱患,所以對這個要點的理解更應該養成是一種程式設計習慣。

首先書上給了一段**作為例子

int priority();

void processwidget(std::tr1::shared_ptrpw, int priority);

這個priority()函式是計算優先順序的,就比如是作業系統中程序的優先順序,然後下面的processwidget函式是乙個處理函式,這個處理函式中第乙個引數用到了乙個智慧型指標,這個智慧型指標是用來管理動態分配的乙個widget,另乙個引數是優先順序。

現在考慮這樣來呼叫這個函式

processwidget(new widget, priority());
但是 這樣是通過不了編譯的,原因在於智慧型指標的建構函式中,利用它指向的元素型別(raw type 這裡就是widget)來構造的函式是explicit的,這就意味著不能進行隱式轉換,解釋一下:

按照原本的想法,應該是先new widget得到乙個指向widget的指標widget*,然後用這個指標去構造shared_ptr< widget > pw, 顯然要進行乙個型別轉換,但是問題就是這個建構函式是explicit修飾的,explicit的意義是在編譯階段就阻止進行隱式轉換,所以無法通過編譯,那怎麼來解決這個問題呢?

很簡單,寫成這樣就可以了

processwidget(std::tr1::shared_ptr( new widget) , priority());
也就是在呼叫的時候寫乙個型別轉換,就能通過編譯。

但是就是這樣一種寫法,也會帶來記憶體洩漏的隱患,這也是item17想強調的地方

來分析一下這種寫法到底發生了什麼,首先它的引數中,肯定是有這樣的三個過程要進行:

這三個過程是在乙個函式呼叫中發生的,在c++中沒有規定這三個過程的發生順序,也就意味著可以有這樣的一種發生順序:

1.new widget

2.priority()

3. std::tr1::shared_ptr< widget >( new widget)

如果按照這樣的順序進行操作,那麼在進行到第二步priority()時,如果發生了異常,那麼後面的第三步就不會再執行,而第三步是對動態分配記憶體管理的至關重要的方法(在item13中強調過),這樣就導致我們會丟失對new產生的記憶體的洩漏。

那麼如何來解決這個問題呢?書上的建議就是把過程1和3與過程2分離開來,具體來說就是

std::tr1::shared_ptrpw(new widget);

processwidget(pw , priority());

這樣第一句完成new widget的過程,同時把它進行型別轉換,放進智慧型指標管理,然後再呼叫process函式進行處理,這樣寫成兩句**的形式就避免了記憶體洩漏的問題。這也就是item17強調的點store new ed objects in smart pointers in standalone statements(在乙個單獨的語句中把new建立的物件存進智慧型指標)

Effective C 學習筆記

學習effective c 已經有相當長的一段時間了,今天抽出時間又堵了一遍第一部分 c語言 c 以c語言為基礎,幾乎支援所有的c語言成分,例如區塊 語句 預處理 內建資料型別 陣列 指標等,c語言的侷限是 沒有模板 沒有異常 沒有過載 物件導向的c 也就是加上了物件特性的c,類 封裝 繼承 多型 ...

Effective C 學習筆記

1 c 是乙個複合式的語言 c 中不同部分有著不同的語言特性,例如 1.1 在c中傳遞形參時,按照值傳遞比按照指標傳遞效率更高 1.2 在物件導向程式中,物件要按照const引用而不是按照值傳遞 1.3 在stl程式設計中採取按照值傳遞方式 所以說c 中沒有統一的準則,要按照不同的特性採取不同的使用...

effective c 學習筆記

如果不考慮應用程式的使用場合,僅僅考慮語言的靈活性,我贊成作者的想法。但是不同的應用它會有不同的效能要求,所以語言的選擇,應該是用 最適合 條款去選擇。使用巨集定義常量,若定義在標頭檔案中,則所有包含標頭檔案的都可以使用。巨集定義,在預處理的時候進行替換。巨集定義一些簡單的函式,可以減少呼叫開銷,但...