Why is "error: invalid application of 'sizeof' to an incomplete type using unique_ptr" fixed by adding an empty destructor?

Why is "error: invalid application of 'sizeof' to an incomplete type using unique_ptr" fixed by adding an empty destructor?

我正在 class STFT 上拉皮条。在 header:

中用这个编译就好了
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
}

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

error: invalid application of 'sizeof' to an incomplete type 'STFT' static_assert(sizeof(_Tp) > 0, "default_delete can not delete incomplete type");

但是,如果我只是提供一个空的析构函数 Whatever::~Whatever(){},那么它可以正常编译。这让我完全难住了。请告诉我这个无意义的析构函数为我做了什么。

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

std::unique_ptr may be constructed for an incomplete type T, such as to facilitate the use as a handle in the Pimpl idiom. If the default deleter is used, T must be complete at the point in code where the deleter is invoked, which happens in the destructor, move assignment operator, and reset member function of std::unique_ptr. (Conversely, std::shared_ptr can't be constructed from a raw pointer to incomplete type, but can be destroyed where T is incomplete).

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

#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(){}

如果在定义 Whatever 的析构函数之前注释 STFT 的定义,则不满足要求,因为这需要 stft 的析构函数,而 stft 又需要 STFT 完成。

因此,在您的 实现 文件中, STFT 似乎很可能在定义 Whatever::~Whatever() 时完成,否则默认创建的文件没有 STFT 完成。

我提供此类析构函数的惯用语是(在实现文件中):

#include "STFT.h"

Whatever::~Whatever() = default;

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