我已经阅读了关于这个主题的其他stackoverflow问题,但我真的对不完整的类型和这个C ++规范段落§5.3.5/ 5感到困惑:
如果要删除的对象的类型不完整 删除和完整的类有一个非平凡的析构函数或 解除分配函数,行为未定义。
举个例子,.h:
class Holder::Impl {};
Holder::Holder() : _mptr(new Impl) {}
Holder::~Holder() {}
的.cpp
{{1}}
类Holder的非内联析构函数如何突然使Impl完成? 为什么默认的析构函数不足以使类完成?为什么shared_ptr在没有析构函数的情况下完美运行?
答案 0 :(得分:4)
这一切都与my_scoped_ptr<Impl>::~my_scoped_ptr
的实例化有关。
当你不提供用户定义的析构函数时,只要处理了类Holder
的定义,就会定义默认的析构函数 - 基本上,它等同于在类中定义析构函数:
class Holder {
// ...
~Holder() {}
};
此析构函数需要销毁_mptr
成员,因此此时~my_scoped_ptr
也会被实例化,而Impl
仍然不完整。
当您在标头中显式声明析构函数并在.cpp文件中定义时,~my_scoped_ptr
的实例化发生在该定义的位置 - 到那时,Impl
已完成。< / p>
std::shared_ptr
通过在运行时,在其构造函数中,在第一次传递原始指针的位置捕获删除器,并将其存储在控制块中来解决此问题。您甚至可以将std::shared_ptr<Derived>
分配给std::shared_ptr<Base>
,后者最终会调用正确的析构函数,即使非虚拟析构函数也是如此。 std::shared_ptr
可以解决这个问题,因为无论如何它需要分配额外的存储空间(对于引用计数等),所以它已经有点重量级了。另一方面,std::unique_ptr
出现与my_scoped_ptr
相同的问题,原因相同。
答案 1 :(得分:0)
头文件中没有完成。
~Holder();
宣布了一个外部函数。
声明~Holder() = default;
等同于声明~Holder() {}
,也就是说它提供了声明的析构函数的定义。它不能这样做,因为内部Impl
类仅在此时被声明,未定义。