關於PIMPL IDIOM(Opaque Pointer)

來源:互聯網
上載者:User

今天看到CSDN的一個討論帖:討論如何隱藏DLL標頭檔細節的作法。http://bbs.csdn.net/topics/390414874

說實話,我之前也有過類似的疑問,也沒有特別好的想法,後來工作一直沒有遇到過這個需求,就漸漸忘記了,其實某一次在miko的blog裡面看到過pimpl的說法,但是還沒有深刻理解,今天通過這個問題和查閱一些資料,終於瞭解了。下面的觀點基本上都是翻譯自[1],似乎在《Effective C++》中有(目前這本書我還沒讀過,積弱啊),我只是做了簡單概括和備份,詳細瞭解還是去[1]這個網址看看吧。

PIMPL應該是Pointer to IMPLementation的縮寫,意指指向實作類別的指標,一個簡單的代碼例子:

// XImpl.hclass XImpl {public:    int  fun();private:    int  m_data;};// XImpl.cpp#include "XImpl.h"int XImpl::fun() { return m_data * 2; }// X.hclass XImpl;  // forword declarationclass X {public:    X();    int  fun();private:    XImpl*  m_handle;};// X.cpp#include "XImpl.h"#include "X.h"X::X() m_handle( new XImpl() ) {}int  X::fun() { return m_handle->fun(); }

類的設計是為了抽象,為了被別的代碼調用,所以我們可以說使用了X類的代碼都是客戶代碼(client code),下面來討論一下PIMPL的優點和缺點。

優點:

1 大大降低了編譯依賴(compile-dependency),進而改善重新編譯速度

因為基本上不需要修改X.h,所以客戶代碼無需重新編譯,當然最終二進位的產生還需要link,這個是必須要做的,但是相對於大項目龐大的編譯時間,這點時間幾乎可以忽略。(很多大項目編譯以小時計,如果修改一處代碼,可能就增加了幾分鐘編譯時間)。下面的[5][6]提到了標準庫中的iosfwd,可以借鑒。

註:目前主流的C++編譯器流程是這樣的:1 先行編譯階段,將所有的#include全部展開;2 對每個源檔案進行編譯,產生obj;3 進行obj的串連,產生二進位結果(例如exe或dll等)。

2 隱藏資料細節

我們知道,如果X類想給客戶使用,必需提供標頭檔聲明,而類的標頭檔往往寫下了類的member-data和member-function,其中member-function可以把實現細節放到cpp中封裝成dll,但是member-data就沒那麼走運了。而XImpl類正好就提供了這個功能。XImpl可以全部隱藏在dll中,而對XImpl的data的任何修改,都無需體現在X類中。

缺點:

1 增加記憶體佔用

我們知道指標會佔用4或8位元組(目前大部分系統),而8位元組並不是一個小數字,很多64bit程式跑不過32bit就和這個指標有莫大關係。還有原文作者提到的位元組對齊(memory aligned)問題,可能會增加更多的無用位元組。

2 已耗用時間增加

指標和數組有什麼區別?答案是:數組是一個常量(它不可以發生變化),而指標是一個變數,所以取指標指向的內容,就要先載入指標的值,然後把這個值看成地址,再去地址取真正的資料,也就是所謂的“解引用”(dereference)。

那麼對m_handle這個指標的任何調用都相當於多了一層解引用的開銷。

多一個new的開銷,我們知道棧(stack)比堆(heap)的資料開闢速度快(棧只需要移動一下棧頂指標,而堆需要考慮記憶體片段,多線程競爭等等),當然也可以用自己實現的new operator加類似記憶體池的方式降低這個消耗,詳見[1]中的論述。

總結:

對於小項目或程式碼片段,這個方式沒什麼優勢。但是對於編譯時間已經不可忽略的大項目,並且不在代碼熱點區,這個方式經常被用到,[2]中提到Qt和KDE中大量使用。

程式員有很多時間都在debug,並且經常需要重新編譯,如果每次rebuild都要幾分鐘,確實讓人boring,盡量將PIMPL這個手段加入到項目中吧。

閱讀材料(按重要性排序):

[1] http://www.gotw.ca/publications/mill05.htm

[2] http://en.wikipedia.org/wiki/Opaque_pointer#cite_note-4

[3] http://hi.baidu.com/yxf_coder/item/9126bfc25eb6562fa1b50a0f

[4] http://stackoverflow.com/questions/60570/why-should-the-pimpl-idiom-be-used

[5] http://www.cplusplus.com/reference/iosfwd/

[6] http://www.cnblogs.com/Solstice/archive/2011/07/17/2108715.html

[7] http://www.oschina.net/code/snippet_102081_2211

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.