删除指向不完整类型和智能指针的指针

19 c++ smart-pointers auto-ptr shared-ptr c++11

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

class A;
...
std::auto_ptr<A> a;
Run Code Online (Sandbox Code Playgroud)

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

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

Jam*_*lis 35

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

初始化或重置a shared_ptr以指向新对象时,它会创建一个"删除器",可用于销毁对象.例如,请考虑以下事项:

// somewhere where A is incomplete:
std::shared_ptr<class A> p;

// define A
class A { /* ... */ };

p.reset(new A());
Run Code Online (Sandbox Code Playgroud)

当你打电话时reset,A完成是因为你正在使用它创建一个实例new.该reset函数在内部创建并存储将用于销毁对象的删除器delete.因为A在这里完成,这delete将是正确的事情.

通过这样做,声明时shared_ptr不要求A完整shared_ptr<A>; 它只需要Ashared_ptr调用获取原始指针的构造函数或使用原始指针调用时完成reset.

请注意,如果A不是当你这样做的这两件事一个完成的,shared_ptr不会做正确的事,这种行为是未定义(这是在解释该文档boost::shared_ptr,这可能是学习如何用最好的资源shared_ptr正确,无论shared_ptr你正在使用哪个版本(Boost,TR1,C++ 0x等)).

但是,只要您始终遵循最佳使用惯例 - shared_ptr例如,如果您始终shared_ptr使用指向调用的指针直接初始化和重置 - 您new将不必担心违反此规则.

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

auto_ptr(unique_ptr也是)被设计成没有任何开销:它上面的操作应该和使用哑指针一样有效.因此,auto_ptr没有这个功能.

  • 以下是unique_ptr和shared_ptr的完整性要求摘要:http://home.roadrunner.com/~hinnant/incomplete.html (6认同)
  • 有关shared_ptr的一小时非常有趣的资料,请查看[STL STL](http://channel9.msdn.com/Shows/Going+Deep/C9-Lectures-Stephan-T-Lavavej-Advanced-STL-1-的-N).另外值得一提的是`std :: make_shared <T>`. (2认同)
  • 谢谢!以下是unique_ptr和shared_ptr的完整性要求摘要的更新链接:http://howardhinnant.github.io/incomplete.html (2认同)