[英]Using std::unique_ptr in an exported class
我在DLL中有一個看起來像這樣的類:
#ifdef LIB_EXPORT
#define LIB_API __declspec(dllexport)
#else
#define LIB_API __declspec(dllimport)
#endif
...
class LIB_API MyClass {
public:
// ...public interface...
private:
// ...some private fields...
std::unique_ptr<OtherClass> otherPtr_;
};
現在,我認為這可能是一個問題:如果客戶端代碼使用的unique_ptr版本略有不同,則MyClass對象的內存布局實際上將與DLL中的代碼有所不同。
我真的不想訴諸於Pimpl慣用法來從公共標頭中隱藏unique_ptr
。 我可能會滾動自己的簡化版本的unique_ptr
(我只需要其功能的子集,例如,我不需要自定義刪除器)。 但是,在嘗試之前,是否還有其他方法可以解決此問題?
您認為的問題是很實際的,它不僅適用於Standard庫類的布局,還適用於您自己的類。 除非您的類滿足標准布局規則,否則即使給定完全相同的源代碼,也不希望不同的編譯器使用相同的內存布局。 答案是完全不應該導出C ++類。
情況#1:如果要用unique_ptr
來管理DLL的公共對象的生存期:
從DLL導出工廠函數和刪除函數,並將包裝器類放在公共頭文件中。 包裝器完全存在於客戶端中,因此僅使用客戶端的unique_ptr
版本。
__declspec(dllexport)
包裝類上使用。
情況2:如果DLL內部使用了unique_ptr
:
應該使用繼承而不是pimpl。 公共頭文件包含一個基類,該基類具有受保護的構造函數,純虛擬成員函數並且完全沒有數據成員。 同樣,不使用__declspec(dllexport)
。 dllexport
工廠函數用於創建新實例。 在DLL中,您將從該接口類型繼承,派生類添加所有數據成員和函數體。 客戶端從未見過任何數據成員,因此您可以自由使用C ++對象,並且所使用的布局是DLL本地的。
這兩個方面的副作用是瑣碎的成員函數將不會被內聯,這可能會對性能產生負面影響。 但是,對每個成員訪問都調用DLL是實現解耦的唯一方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.