【问题标题】:Deletion of pointer to incomplete type and smart pointers删除指向不完整类型和智能指针的指针
【发布时间】:2011-08-02 04:20:33
【问题描述】:

当尝试使用带有前向声明声明的类型的 auto_ptr 时,如下所示:

class A;
...
std::auto_ptr<A> a;

A 的析构函数没有被调用(显然是因为auto_ptr 内部deletes 的底层指针和不完整类型的析构函数不能被调用)。

但是,相同的代码可以正常工作,并且在使用 std::shared_ptr 而不是 std::auto_ptr 时会调用析构函数。 怎么解释?

【问题讨论】:

    标签: c++ c++11 shared-ptr smart-pointers auto-ptr


    【解决方案1】:

    shared_ptr 可以声明为不完整的类型,是的。在初始化或重置类型之前,该类型不需要完整。

    当您初始化或重置shared_ptr 以指向一个新对象时,它会创建一个可用于销毁该对象的“删除器”。例如,考虑以下情况:

    // somewhere where A is incomplete:
    std::shared_ptr<class A> p;
    
    // define A
    class A { /* ... */ };
    
    p.reset(new A());
    

    当您调用 reset 时,A 已完成,因为您正在使用 new 创建它的实例。 reset 函数在内部创建并存储一个删除器,该删除器将用于使用delete 销毁对象。因为A 在这里是完整的,所以delete 会做正确的事情。

    通过这样做,shared_ptr 不要求在声明 shared_ptr&lt;A&gt;A 是完整的;它只要求A 在调用带有原始指针的shared_ptr 构造函数时或当您使用原始指针调用reset 时完成。

    请注意,如果 A 在您执行这两件事之一时完整,shared_ptr 将不会做正确的事情并且行为未定义(这在 @987654321 中进行了解释@,这可能是学习如何正确使用 shared_ptr 的最佳资源,无论您使用的是哪个版本的 shared_ptr(Boost、TR1、C++0x 等)。

    但是,只要您始终遵循 shared_ptr 的最佳使用实践--值得注意的是,如果您始终使用调用 new 产生的指针直接初始化和重置 shared_ptr--您将不会不必担心违反此规则。

    这个功能不是免费的:shared_ptr 必须创建并存储一个指向删除函子的指针;通常这是通过将删除器存储为存储强和弱引用计数的块的一部分或通过将指针作为指向删除器的块的一部分来完成的(因为您可以提供自己的删除器)。

    auto_ptr(以及unique_ptr)被设计为没有任何开销:对其的操作应该与使用哑指针一样有效。因此,auto_ptr 没有此功能。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-31
    • 2012-08-15
    相关资源
    最近更新 更多