为什么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() = default
或Foo::~Foo() {}
,它可以看到~Bar
在~std::unique_ptr<Bar>
被调用的点,一切都很好。
这在实践中很重要,因为 Bar
的销毁方式取决于 ~Bar
是否是虚拟的,如果 Bar
有 parents,如果 ~Bar
] 是 private/protected 调用可能是非法的。
如果我有 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() = default
或Foo::~Foo() {}
,它可以看到~Bar
在~std::unique_ptr<Bar>
被调用的点,一切都很好。
这在实践中很重要,因为 Bar
的销毁方式取决于 ~Bar
是否是虚拟的,如果 Bar
有 parents,如果 ~Bar
] 是 private/protected 调用可能是非法的。