c++ - 空指针 - 我使用哪种指针?




c++空指针 (3)

好的,所以最后一次我为了生活而编写C ++, std::auto_ptr是所有可用的std lib, boost::shared_ptr都是愤怒。 我从来没有真正考虑过提供的其他智能指针类型提升。 我知道C ++ 11现在提供了一些类型的提升,但不是全部。

那么有人有一个简单的算法来确定何时使用哪个智能指针? 优选地包括关于哑指针(诸如T*原始指针)和其余的增强智能指针的建议。 (像this东西会很棒)。


共享所有权:
采用的标准shared_ptrweak_ptr几乎与其Boost对应的标准相同。 当你需要共享一个资源并且不知道哪一个是最后一个活着的时候使用它们。 使用weak_ptr观察共享资源而不影响其生命周期,而不是打破循环。 使用shared_ptr循环通常不会发生 - 两个资源不能彼此拥有。

请注意,Boost还提供了shared_array ,它可能是shared_ptr<std::vector<T> const>一个合适的替代方案。

接下来,Boost提供了intrusive_ptr ,如果您的资源已经提供了引用计数管理,并且您希望将其采用到RAII原则,那么这是一种轻量级解决方案。 这个标准没有被采用。

独特所有权:
Boost也有一个scoped_ptr ,它不可复制,并且您无法指定删除者。 std::unique_ptrboost::scoped_ptr类固醇, 当你需要一个智能指针时 ,它应该是你的默认选择 。 它允许您在其模板参数中指定一个删除器,并且可移动 ,与boost::scoped_ptr不同。 只要您不使用需要可复制类型的操作(显然),它也可以在STL容器中完全使用。

再次注意,Boost有一个数组版本: scoped_array ,它通过要求std::unique_ptr<T[]>部分专用化来delete[]指针,而不是delete它(使用default_delete r)来统一std::unique_ptr<T[]>std::unique_ptr<T[]>也提供了operator[]而不是operator*operator->

请注意, std::auto_ptr仍处于标准状态,但不推荐使用§D.10 [depr.auto.ptr]

类模板auto_ptr已弃用。 [ 注意:类模板unique_ptr (20.7.1)提供了更好的解决方案。 - 注意 ]

没有所有权:
使用哑指针(原始指针) 或非拥有引用引用资源,并且知道资源将超过引用对象/作用域。 当您需要可空性或可重置性时,首选参考并使用原始指针。

如果您想要对资源拥有非拥有的引用,但不知道资源是否会超过引用该资源的对象,请将资源打包到shared_ptr并使用weak_ptr - 您可以测试父级shared_ptr是否处于活动状态lock ,如果资源仍然存在,它将返回非null的shared_ptr 。 如果想测试资源是否死亡,请使用expired 。 这两者可能听起来很相似,但在并发执行方面却非常不同,因为expired仅保证其对于单个语句的返回值。 像一个看似无辜的测试

if(!wptr.expired())
  something_assuming_the_resource_is_still_alive();

是一种潜在的竞争条件。


何时使用unique_ptr的情况:

  • 工厂方法
  • 是指针的成员(包括pimpl)
  • 在stl容器中存储指针(以避免移动)
  • 使用大型本地动态对象

何时使用shared_ptr的情况:

  • 跨线程共享对象
  • 绑定或捕获指针(使用lambda或std :: bind)
  • 一般共享对象
  • 自定义删除者

何时使用weak_ptr的情况:

  • 充当通用参考的大型地图(来自所有开放式套接字的地图)

随意编辑和添加更多


除非需要引用计数,否则请使用unique_ptr<T> ,在这种情况下,请使用shared_ptr<T> (对于非常罕见的情况,使用weak_ptr<T>以防止引用循环)。 在几乎所有情况下,可转让的独特所有权都很好。

生指针:只有当你需要协变回报时,才有可能发生。 否则它们并不是非常有用。

数组指针: unique_ptr具有针对T[]的特殊功能,可以自动调用结果中的delete[] ,因此您可以安全地执行unique_ptr<int[]> p(new int[42]); 例如。 shared_ptr你仍然需要一个定制的删除器,但你不需要专门的共享或唯一的数组指针。 当然,这样的东西通常最好由std::vector代替。 不幸的是, shared_ptr没有提供数组访问函数,所以你仍然需要手动调用get() ,但是unique_ptr<T[]>提供了operator[]而不是operator*operator-> 。 无论如何,你必须检查自己。 这使得shared_ptr用户友好性略差一些,尽管可以说泛型优点和Boost依赖性都不再使得unique_ptrshared_ptr成为赢家。

作用域指针:与unique_ptr无关,就像auto_ptr一样。

没有什么比这更多的了。 在没有移动语义的C ++ 03中,这种情况非常复杂,但在C ++ 11中,建议非常简单。

其他智能指针仍然有用,如intrusive_ptrinterprocess_ptr 。 但是,在一般情况下,它们非常小众,完全没有必要。





c++-faq