为什么unique_ptr<T>::~unique_ptr需要T的定义?

Why does unique_ptr<T>::~unique_ptr need the definition of T?

如果我有 class 'Bar':

// bar.h
class Bar
{
public:

    Bar() { }
};

我转发声明在另一个 class 'Foo':

中使用 std::unique_ptr
// foo.h
#include <memory>

class Bar;

class Foo
{

public:

    Foo();

private:

    std::unique_ptr<Bar> bar_;
};

以及我在 Foo 的实现文件中包含的定义:

// foo.cpp
#include "foo.h"
#include "bar.h"

Foo::Foo()
: bar_(new Bar)
{ }

我收到编译时错误 "Invalid application of 'sizeof' to an incomplete type 'Bar'"。

我从 here and here 了解到要解决这个问题,我可以在 foo.h 中声明 Foo 的析构函数并将其空定义移动到 foo.cpp。我不明白的是,为什么要修复它。我读到 std::unique_ptr 有时需要知道其类型的完整定义。如果我必须从 bar.h 中包含 Bar 以便 unique_ptr 看到它的定义,这对我来说是有意义的。但是 Foo 的析构函数与 Bar 的可见性有什么关系,为什么在 foo.h 中声明 ~Foo() 并在 foo.cpp 中定义它会消除错误?

unique_ptr<Bar> 的析构函数在 delete 是它拥有的 Bar 时调用 Bar::~Bar。所以 ~unique_ptr<Bar> 需要看到 Bar::~Bar.

但模板方法仅在使用时实例化。

唯一指针被Foo::~Foo中的Foo破坏了。如果 ~Foo 位于可以看到 ~Bar 的定义的地方,那么一切都很好。

如果让它由编译器生成,它'lives'在Foo的声明中,它看不到~Bar

如果你前向声明它,然后在.cpp文件中#include <bar.h>之后做一个Foo::~Foo() = defaultFoo::~Foo() {},它可以看到~Bar~std::unique_ptr<Bar> 被调用的点,一切都很好。

这在实践中很重要,因为 Bar 的销毁方式取决于 ~Bar 是否是虚拟的,如果 Bar 有 parents,如果 ~Bar ] 是 private/protected 调用可能是非法的。