【问题标题】:Why does unique_ptr<T>::~unique_ptr need the definition of T?为什么 unique_ptr<T>::~unique_ptr 需要 T 的定义?
【发布时间】:2015-04-15 19:32:33
【问题描述】:

如果我有一个类“酒吧”:

// bar.h
class Bar
{
public:

    Bar() { }
};

我转发声明与另一个类 '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)
{ }

我收到编译时错误“'sizeof' 对不完整类型 'Bar' 的无效应用”。

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

【问题讨论】:

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


    【解决方案1】:

    unique_ptr&lt;Bar&gt; 的析构函数在 delete 是它所拥有的 Bar 时调用 Bar::~Bar。所以~unique_ptr&lt;Bar&gt; 需要看到Bar::~Bar

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

    唯一的指针被Foo::~Foo 中的Foo 销毁。如果~Foo 生活在它可以看到~Bar 定义的地方,那么一切都很好。

    如果您让它由编译器生成,它会“存在”在Foo 的声明中,在那里它看不到~Bar

    如果你转发声明它,然后在.cpp文件中#include &lt;bar.h&gt;之后做一个Foo::~Foo() = defaultFoo::~Foo() {},它可以在~std::unique_ptr&lt;Bar&gt;被调用的地方看到~Bar`,一切都是不错。

    这在实践中很重要,因为 Bar 的销毁方式会有所不同,具体取决于 ~Bar 是否为虚拟,Bar 是否有父级,以及 ~Bar 是否为私有/受保护的,调用可能是非法的。

    【讨论】:

    • "如果你让它由编译器生成,它会'存在'在 Foo 的声明中,它看不到 ~Bar"。这是因为编译器生成的析构函数是自动内联的吗?
    • @vsoftco 它还能去哪里?没有翻译单位有优先权。
    猜你喜欢
    • 2012-07-07
    • 2015-07-23
    • 1970-01-01
    • 2011-08-26
    • 1970-01-01
    • 2014-10-12
    • 1970-01-01
    • 2015-08-10
    • 2020-04-17
    相关资源
    最近更新 更多