为什么unique_ptr <t> ::〜unique_ptr需要定义T?</t>

时间:2015-02-15 00:49:46

标签: c++ c++11 std smart-pointers

如果我有课程&#39; Bar&#39;:

// bar.h
class Bar
{
public:

    Bar() { }
};

我转发声明在另一个类中使用std :: unique_ptr&#39; Foo&#39;:

// 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)
{ }

我收到编译时错误&#34;&#39; sizeof&#39;的无效应用程序不完整的类型&#39; Bar&#39;&#34;。

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

1 个答案:

答案 0 :(得分:8)

unique_ptr<Bar>的析构函数在Bar::~Bar拥有delete时调用Bar。因此~unique_ptr<Bar>需要查看Bar::~Bar

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

唯一的ptr被Foo中的Foo::~Foo破坏。如果~Foo生活在可以看到~Bar定义的地方,那么一切都很好。

如果你让它由编译器生成,那么它“存在”Foo的声明中,它无法看到~Bar

如果您转发声明,请在Foo::~Foo() = default之后在Foo::~Foo() {}文件中执行.cpp#include <bar.h>,它可以在~Bar处看到~std::unique_ptr<Bar> Bar被称为`,一切都很好。

这在实践中很重要,因为销毁~Bar的方式会有所不同,具体取决于Bar是否为虚拟,~Bar是否有父母,{{1}}是私有/受保护的打电话可能是违法的。