为什么"错误:无法应用' sizeof'使用unique_ptr"到不完整的类型通过添加一个空的析构函数来修复?

时间:2015-12-03 17:51:03

标签: c++ c++11 unique-ptr pimpl-idiom

我正在上课STFT。在标题中编译就好了:

class STFT; // pimpl off to prevent point name clash

class Whatever
{
private:
    STFT* stft;

这在实施中:

#include "STFT.h"
Whatever::Whatever() : stft(new STFT()) {
// blah blah
}

Whatever::~Whatever() {
    delete stft; // pure evil
}

但是,切换到标题中原始指针的std::unique_ptr<STFT> stft;,并删除析构函数,我得

  

错误:无法应用&#39; sizeof&#39;到一个不完整的类型&#39; STFT&#39;               static_assert(sizeof(_Tp)&gt; 0,&#34; default_delete无法删除不完整的类型&#34;);

但是,如果我只提供一个空的析构函数Whatever::~Whatever(){},那么它编译得很好。这让我完全难过。请填写我这个毫无意义的析构函数为我做的事情。

2 个答案:

答案 0 :(得分:10)

因此,如果我们转到std::unique_ptr的cppreference文档:

  

std :: unique_ptr可以为不完整的类型T构造,例如   便于在Pimpl成语中用作句柄。 如果是默认值   使用删除器,T必须在代码所在的位置完成   调用deleter,它发生在析构函数中,移动赋值   运算符,并重置std :: unique_ptr 的成员函数。 (反过来,   std :: shared_ptr无法从原始指针构造为不完整   类型,但可以在T不完整的情况下销毁。

我们可以在下面的代码中看到:

#include <memory>

class STFT; // pimpl off to prevent point name clash

class Whatever
{
    public:
     ~Whatever() ;
    private:
      std::unique_ptr<STFT> stft;
} ;

//class STFT{};

Whatever::~Whatever() {}

int main(){}

在定义STFT的析构函数之前评论Whatever的定义时,未满足要求,因为这需要stft的析构函数,而这需要STFT完成。

因此,在定义STFT时,实现文件Whatever::~Whatever()中的文件很可能已完成,但在没有STFT完成的情况下创建默认文件

答案 1 :(得分:3)

我提供这种析构函数的常用习惯是

Whatever::~Whatever() = default;

重要的是它需要在指向类型完整的地方。