簡體   English   中英

在導出的類中使用std :: unique_ptr

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM