[英]QScopedPointer, boost::scoped_ptr - why complaining about incomplete types?
我有c-Structure,我想嵌入一個cpp類而不會中毒我的全局命名空間,所以我不想包含c-header。
這就是為什么我想使用具有前向聲明結構名稱的智能范圍指針( QScopedPointer
或boost::scoped_ptr
)。
我不明白的是在編譯時失敗的兩個提到的作用域指針的實現:
促進:
錯誤C2027:使用未定義類型'xxx'
template<class T> inline void checked_delete(T * x)
{
// intentionally complex - simplification causes regressions
typedef char type_must_be_complete[ sizeof(T)? 1: -1 ]; // < here
(void) sizeof(type_must_be_complete);
delete x;
}
在Qt中也是如此:
錯誤C2027:使用未定義類型'xxx'
template <typename T>
struct QScopedPointerDeleter
{
static inline void cleanup(T *pointer)
{
// Enforce a complete type.
// If you get a compile error here, read the section on forward declared
// classes in the QScopedPointer documentation.
typedef char IsIncompleteType[ sizeof(T) ? 1 : -1 ]; // < here
(void) sizeof(IsIncompleteType);
delete pointer;
}
};
引用的文檔沒有幫助我。 它表示前向聲明的類的析構函數不必是內聯的,並且必須在每個可能的范圍內清除指定指針時都可用。 但我的c結構沒有析構函數。
所以我有兩個問題:
我的c-Structure沒有析構函數。
一方面, 不 。 你的struct實際上有一個析構函數 - 隱式聲明的析構函數 。
無論如何,讓我們繼續吧。
delete pointer;
編譯這段代碼時,我們應該調用*pointer
的析構函數。 但是,如果*pointer
是不完整類型,我們無法知道要調用的析構函數。 在這種情況下,標准[expr.delete]表示它會導致未定義的行為 。
如果被刪除的對象在刪除時具有不完整的類類型,並且完整的類具有非平凡的析構函數或釋放函數 ,則行為是未定義的。
如您所見,如果您的結構沒有非平凡的析構函數或釋放函數(特定於類的operator delete
),那么它不是UB。 但是,您可能可以在結構中添加析構函數 - 您將這樣做。 如果你沒有解決這一點,它就變成了錯誤的bug。 (編譯器不必報告它;它只是UB,而不是非法代碼。)所以它不被認為是一種好的做法。
因此,刪除不完整的類型確實是我們應該避免的。 為避免這種情況,我們使用了這個技巧。
typedef char type_must_be_complete[ sizeof(T)? 1: -1 ]; // < here
(void) sizeof(type_must_be_complete);
因為如果T
是不完整類型, sizeof(T)
是非法代碼,所以它可以減少編譯時錯誤,因為UB導致程序瘋狂。
盡管補償速度較慢,我強烈建議您盡量包括它; 雖然您的結構很簡單,並且沒有operator delete
,但可以在不修復的情況下添加它們,這會導致UB。
也許這個鏈接可以幫助你解決這個問題: http : //www.bnikolic.co.uk/blog/cpp-checked-delete.html
由於“boost / checked_delete.hpp”標頭, scoped_ptr需要使用完全定義的類型作為模板參數。
就個人而言,我更喜歡std :: unique_ptr用於這些類型的東西(例如,隱藏實現,當用於某些構造的Init()方法是私有的時)但是boost沒有唯一的指針。
有時你可以使用boost :: shared_ptr ,這取決於你需要什么,因為它不表達這些錯誤。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.