我正在上课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(){}
,那么它编译得很好。这让我完全难过。请填写我这个毫无意义的析构函数为我做的事情。
答案 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;
重要的是它需要在指向类型完整的地方。