簡體   English   中英

QScopedPointer,boost :: scoped_ptr - 為什么抱怨不完整的類型?

[英]QScopedPointer, boost::scoped_ptr - why complaining about incomplete types?

我有c-Structure,我想嵌入一個cpp類而不會中毒我的全局命名空間,所以我不想包含c-header。

這就是為什么我想使用具有前向聲明結構名稱的智能范圍指針( QScopedPointerboost::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結構沒有析構函數。

所以我有兩個問題:

  1. 為什么這個檢查呢? 因為知道調用delete的大小似乎無關緊要。
  2. 怎么處理這個?
  1. 必須在智能指針被破壞的地方知道保存在智能指針中的對象類型,因此可以調用保留對象的正確析構函數
  2. 你的類(持有智能指針的那個)有析構函數嗎? 如果不是 - 在cpp文件中添加一個。 否則,編譯器會在看到您的類定義時嘗試添加一個,但由於智能指針的析構函數嘗試訪問未知類型,因此無法執行此操作。

我的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.

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