2016-01-28 77 views
2

這不是一個騙局std::unique_ptr with an incomplete type won't compileunique_ptr pimpl和不完整類型

考慮下面的代碼:

#include <memory> 

struct X 
{ 
    X(); 
    ~X();  

    struct Impl; 
    std::unique_ptr<Impl> up_; 
}; 

struct Impl {}; // fully visible here 

X::X() : up_{nullptr}{} 
X::~X() = default; 

int main() 
{ 
    X x; 
} 

Live on Coliru

GCC /鐺都吐了一個錯誤,指出Impl是不完整的。但是,我提供X的默認析構函數之後Impl是完全可見的,因此IMO應該編譯代碼。 爲什麼不呢?現在到了驚喜:如果我讓Impl一個內部類,即定義

struct X::Impl{}; 

代替,然後the code compiles,甚至沒有提供析構函數。 這是怎麼發生的?我們不應該提供這樣一個默認析構函數,至少根據第一行中提到的鏈接?

+2

你說的「//完全可見」;這是與'struct X'中聲明的不同的類。嘗試在'struct X'之前移動'struct Impl;'。 –

+0

@RichardCritten我認爲結構應該在後面定義的'X'的析構函數中完全可見。至少這是我對'unique_ptr'實現PIMPL的理解。 – vsoftco

+1

在最初編寫的代碼中,有兩個不相關的事物,名爲'Impl'。你已經聲明瞭'X :: Impl',但從未定義 - 這是'up_'使用的。然後是':: Impl',它已被定義但從未使用過。當你編寫'struct X :: Impl {};'時,你現在已經聲明和定義了一個名爲'X :: Impl'的類型。 –

回答

11

您有兩個不同的結構名爲Impl

struct X 
{ 
    struct Impl; // Here you declare X::Impl 
    std::unique_ptr<Impl> up_; // Here you create a pointer to a X::Impl 
}; 

struct Impl {}; // Here you declare and define ::Impl 

... 

int main() 
{ 
    X x; // Here X::Impl is still incomplete 
}