2016-01-28 22 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 
}