【问题标题】:Why scoped pointers in boost为什么提升范围内的指针
【发布时间】:2012-05-24 00:02:58
【问题描述】:

作用域指针的目标是什么?据我了解,作用域指针管理代码块中的内存。如果我想在一个块中声明一个变量,我可以在堆栈上声明它而不用担心清理。

【问题讨论】:

标签: c++ boost scoped-ptr


【解决方案1】:

如果它是动态大小或类型,则不会。此外,作用域指针可以交换,在 C++11 中 unique_ptr 可以移动,因此它们不是严格作用域的。

【讨论】:

  • 除了“使用scoped_ptr而不是auto_ptr的主要原因是让您的代码读者知道您打算将“资源获取即初始化”仅应用于当前范围,并且无意转让所有权”...似乎swap 不是预期用途。
  • @BenVoigt:但是提供了,可以使用。
  • 这里是an old thread 讨论为什么swap 成为要求(基本上所以scoped_ptr 可以用作可复制类的成员)。
  • 动态大小或类型是什么意思?
【解决方案2】:

与基于堆栈的数据不同,scoped_ptr 有一个 reset() 成员——换句话说,您可以根据自己的意愿构建/破坏。有了这个,您可以使用空指针(技术上为operator unspecified-bool-type)作为标志,指示在任何给定时间是否存在构造对象。如果需要,它还允许您独立于变量范围对构造/销毁进行排序。

另外,考虑到您可以将 scoped_ptr 声明为类成员,而不仅仅是堆栈变量。 docs 建议使用 scoped_ptr 来实现句柄/正文习语(隐藏类的实现细节)。

最后,为了详细说明 DeadMG 的观点“如果它是动态类型的则不是”,您可以使用 scoped_ptr 来实现 polymorphic 操作:

{
scoped_ptr<Base> a( mode ? new DerivedA : new DerivedB );
a->polymorphic_function();
}

简单基于堆栈的分配实际上不可能做到这一点。


另见此处:C++0x unique_ptr replaces scoped_ptr taking ownership?

【讨论】:

  • boost::variant&lt;DerivedA, DerivedB&gt;。 :)
  • @GManNickG:我不认为 boost::variant 通过 scoped_ptr 很好地替代了多态性——不过很有趣。谢谢!
  • 我看不到如何通过基类接口访问派生类。也许我错过了什么。
  • 知道了:boost::variant&lt;DerivedA,DerivedB&gt; v = DerivedB(); Base &amp; r = boost::get&lt;DerivedB&gt;(v); r.polymorphic_function(); 酷。
【解决方案3】:

关键是您可以在某个词法范围内创建和清理指针。这在各种情况下都很有用,并且如果您要明确使用 new,它会通过忘记 delete 来确保您没有内存泄漏,这是不推荐的。

您应该记住,boost::scoped_ptr 不可复制,因此在其整个生命周期内完全拥有它的资源。这也使它比boost::shared_ptr 更安全,因为它避免了复制资源或意外共享它。

{ //Some Scope

  boost::scoped_ptr<int> i_ptr;
  // do something with pointer

} // leave scope, pointer is cleaned up

【讨论】:

    【解决方案4】:

    通常线程堆栈有内存限制(请参阅线程堆栈大小)。

    有时指针可能已从外部传递给您,需要在此范围内删除(例如,如果抛出异常,则不会执行该行下方的任何删除调用)。所以你需要某种方式自动清理指针

    void foo(Object*obj)
    {
        //this will ensure that object gets cleaned up even if doFoo() throws an exception
        boost::scoped_ptr<Object> objCleaner(obj);
        obj->doFoo();
    }
    

    【讨论】:

    • 我可以在堆栈上声明指针,当函数成功或通过异常超出范围时,它将自动清除。对吗?
    • { X* x = &someObj;这不会导致指针 x 在超出范围时被删除。 someObj 超出范围时将被删除。 {X* y = new X();} 这种类型的代码需要作用域 ptr 来自动清理
    猜你喜欢
    • 2013-01-29
    • 2011-07-22
    • 2021-09-17
    • 1970-01-01
    • 2023-01-25
    • 2011-02-26
    • 2016-03-06
    • 2013-05-07
    • 1970-01-01
    相关资源
    最近更新 更多