問題描述
我正在閱讀 Herb Sutter 的 Exceptional C++" 一書,在這本書中我了解了 PIMPL 習(xí)語.基本上,這個想法是為 class
的 private
對象創(chuàng)建一個結(jié)構(gòu),并動態(tài)分配它們以減少編譯時間(并隱藏以更好的方式私有實現(xiàn)).
I am reading the book "Exceptional C++" by Herb Sutter, and in that book I have learned about the PIMPL idiom. Basically, the idea is to create a structure for the private
objects of a class
and dynamically allocate them to decrease the compilation time (and also hide the private implementations in a better manner).
例如:
class X
{
private:
C c;
D d;
} ;
可以改為:
class X
{
private:
struct XImpl;
XImpl* pImpl;
};
并且,在 .cpp 文件中,定義:
and, in the .cpp file, the definition:
struct X::XImpl
{
C c;
D d;
};
這看起來很有趣,但我以前從未見過這種方法,無論是在我工作過的公司中,還是在我見過源代碼的開源項目中.所以,我想知道這個技術(shù)真的在實踐中使用過嗎?
This seems pretty interesting, but I have never seen this kind of approach before, neither in the companies I have worked, nor in open source projects that I've seen the source code. So, I am wondering it this technique is really used in practice?
我應(yīng)該到處使用它還是謹慎使用它?是否推薦在嵌入式系統(tǒng)中使用這種技術(shù)(性能非常重要)?
Should I use it everywhere, or with caution? And is this technique recommended to be used in embedded systems (where the performance is very important)?
推薦答案
所以,我想知道這種技術(shù)真的用于實踐嗎?我應(yīng)該在任何地方使用它,還是謹慎使用?
So, I am wondering it this technique is really used in practice? Should I use it everywhere, or with caution?
當(dāng)然是用了.我在我的項目中使用它,幾乎在每個課程中.
Of course it is used. I use it in my project, in almost every class.
在開發(fā)庫時,您可以向 XImpl
添加/修改字段,而不會破壞與客戶端的二進制兼容性(這意味著崩潰!).由于向 Ximpl
類添加新字段時 X
類的二進制布局不會改變,因此在次要版本更新中向庫添加新功能是安全的.
When you're developing a library, you can add/modify fields to XImpl
without breaking the binary compatibility with your client (which would mean crashes!). Since the binary layout of X
class doesn't change when you add new fields to Ximpl
class, it is safe to add new functionality to the library in minor versions updates.
當(dāng)然,您也可以在不破壞二進制兼容性的情況下向 X
/XImpl
添加新的公共/私有非虛擬方法,但這與標(biāo)準(zhǔn)頭文件相當(dāng)/實現(xiàn)技術(shù).
Of course, you can also add new public/private non-virtual methods to X
/XImpl
without breaking the binary compatibility, but that's on par with the standard header/implementation technique.
如果您正在開發(fā)一個庫,尤其是專有庫,最好不要透露使用了哪些其他庫/實現(xiàn)技術(shù)來實現(xiàn)您的庫的公共接口.要么是因為知識產(chǎn)權(quán)問題,要么是因為您認為用戶可能會傾向于對實現(xiàn)進行危險的假設(shè),或者只是通過使用可怕的轉(zhuǎn)換技巧來破壞封裝.PIMPL 解決/減輕了這個問題.
If you're developing a library, especially a proprietary one, it might be desirable not to disclose what other libraries / implementation techniques were used to implement the public interface of your library. Either because of Intellectual Property issues, or because you believe that users might be tempted to take dangerous assumptions about the implementation or just break the encapsulation by using terrible casting tricks. PIMPL solves/mitigates that.
編譯時間減少,因為當(dāng)您向XImpl
類添加/刪除字段和/或方法時,只需要重建X
的源(實現(xiàn))文件(這映射到在標(biāo)準(zhǔn)技術(shù)中添加私有字段/方法).在實踐中,這是一個常見的操作.
Compilation time is decreased, since only the source (implementation) file of X
needs to be rebuilt when you add/remove fields and/or methods to the XImpl
class (which maps to adding private fields/methods in the standard technique). In practice, it's a common operation.
使用標(biāo)準(zhǔn)的頭/實現(xiàn)技術(shù)(沒有 PIMPL),當(dāng)你向 X
添加一個新字段時,每一個分配了 X
的客戶端(在堆棧上,或者on heap) 需要重新編譯,因為它必須調(diào)整分配的大小.好吧,每個從未分配過 X 的客戶端都需要重新編譯,但這只是開銷(客戶端的結(jié)果代碼將相同).
With the standard header/implementation technique (without PIMPL), when you add a new field to X
, every client that ever allocates X
(either on stack, or on heap) needs to be recompiled, because it must adjust the size of the allocation. Well, every client that doesn't ever allocate X also need to be recompiled, but it's just overhead (the resulting code on the client side will be the same).
更重要的是,即使在將私有方法 X::foo()
添加到 XClient1.cpp
時,也需要重新編譯標(biāo)準(zhǔn)頭/實現(xiàn)分離 XClient1.cpp
code>X 和 Xh
發(fā)生了變化,即使 XClient1.cpp
由于封裝原因不可能調(diào)用此方法!像上面一樣,它是純粹的開銷,并且與現(xiàn)實生活中的 C++ 構(gòu)建系統(tǒng)的工作方式有關(guān).
What is more, with the standard header/implementation separation XClient1.cpp
needs to be recompiled even when a private method X::foo()
was added to X
and X.h
changed, even though XClient1.cpp
can't possibly call this method for encapsulation reasons! Like above, it's pure overhead and is related with how real-life C++ build systems work.
當(dāng)然,當(dāng)您只是修改方法的實現(xiàn)時不需要重新編譯(因為您不接觸標(biāo)頭),但這與標(biāo)準(zhǔn)標(biāo)頭/實現(xiàn)技術(shù)相當(dāng).
Of course, recompilation is not needed when you just modify the implementation of the methods (because you don't touch the header), but that's on par with the standard header/implementation technique.
是否建議在嵌入式系統(tǒng)中使用這種技術(shù)(性能非常重要)?
Is this technique recommended to be used in embedded systems (where the performance is very important)?
這取決于你的目標(biāo)有多強大.然而,這個問題的唯一答案是:衡量和評估您的所得和損失.此外,請注意,如果您不發(fā)布旨在供客戶在嵌入式系統(tǒng)中使用的庫,則只有編譯時間優(yōu)勢適用!
That depends on how powerful your target is. However the only answer to this question is: measure and evaluate what you gain and lose. Also, take into consideration that if you're not publishing a library meant to be used in embedded systems by your clients, only the compilation time advantage applies!
這篇關(guān)于PIMPL 成語真的在實踐中使用嗎?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網(wǎng)!