为了账号安全,请及时绑定邮箱和手机立即绑定

什么时候使用哪种指针?

什么时候使用哪种指针?

C++ C
白衣染霜花 2019-06-20 10:54:46
什么时候使用哪种指针?好吧,我最后一次写C+是为了谋生,std::auto_ptr所有的STD库都可用,boost::shared_ptr都很疯狂。我从来没有真正研究过其他智能指针类型提供的Boost。据我所知,C+11现在提供了一些类型Boost,但不是所有这些类型。那么,是否有人有一个简单的算法来确定何时使用哪个智能指针?最好包括关于哑指针的建议(原始指针如T*)和其他的Boost智能指针。(有点像这,这个会很棒的)。
查看完整描述

3 回答

?
哈士奇WWW

TA贡献1799条经验 获得超6个赞

共有所有权:
这个shared_ptrweak_ptr所采用的标准与其Boost对口..当您需要共享资源时使用它们,而不知道哪个资源将是最后一个活着的资源。使用weak_ptr观察共享资源而不影响其生存期,而不是中断周期。循环shared_ptr正常情况下不应该发生-两种资源不能互相拥有。

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

接下来,增加报价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_deleter)。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,它将返回shared_ptr如果资源仍然存在,则为非空。如果要测试资源是否已死,请使用expired..这两者听起来可能很相似,但在并行执行的情况下却有很大的不同,如expired仅保证该语句的返回值。看似无辜的考验

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

是一种潜在的种族状况。


查看完整回答
反对 回复 2019-06-20
?
吃鸡游戏

TA贡献1829条经验 获得超7个赞

决定使用哪个智能指针是一个问题所有权..当涉及到资源管理时,对象A拥有对象B如果它控制着对象B的生存期。例如,成员变量由它们各自的对象拥有,因为成员变量的生存期与对象的生存期相关联。根据对象的拥有方式选择智能指针。

请注意,软件系统中的所有权与所有权是分开的,就像我们在软件之外所认为的那样。例如,一个人可能“拥有”他们的家,但这并不一定意味着Person对象的生存期具有控制权。House对象。将这些真实世界的概念和软件概念混为一谈是一种让自己陷入困境的可靠方法。


如果您拥有该对象的唯一所有权,请使用std::unique_ptr<T>.

如果您共享了对象的所有权.
-如果没有所有权周期,则使用std::shared_ptr<T>.
-如果有周期,定义一个“方向”并使用std::shared_ptr<T>在一个方向std::weak_ptr<T>在另一个。

如果对象拥有您,但可能没有所有者,则使用普通指针。T*(例如父指针)。

如果对象拥有您(或以其他方式保证存在),请使用引用。T&.


警告:要注意智能指针的成本。在内存或性能有限的环境中,只使用普通指针和更手动的内存管理方案可能是有益的。

费用:

  • 如果您有一个自定义删除器(例如,您使用分配池),那么这将导致每个指针的开销,这很容易通过手动删除来避免。
  • std::shared_ptr

    具有复制上的引用计数增量的开销,加上销毁时的减少,然后进行0计数检查并删除所保存的对象。根据实现的不同,这会使您的代码膨胀并导致性能问题。
  • 编译时间。与所有模板一样,智能指针对编译时间有负面贡献。

例子:

struct BinaryTree{
    Tree* m_parent;
    std::unique_ptr<BinaryTree> m_children[2]; // or use std::array...};

二叉树并不拥有它的父树,但是树的存在意味着它的父树(或nullptr),因此使用普通指针。二叉树(具有值语义)拥有其子树的唯一所有权,因此std::unique_ptr.

struct ListNode{
    std::shared_ptr<ListNode> m_next;
    std::weak_ptr<ListNode> m_prev;};

在这里,列表节点拥有它的下一个列表和前一个列表,因此我们定义了一个方向,并使用shared_ptr接下来weak_ptr让普雷夫打破这个循环。


查看完整回答
反对 回复 2019-06-20
  • 3 回答
  • 0 关注
  • 453 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信