【问题标题】:Is it good practice to pass scoped_ptr by reference (from one method to another inside a class)?通过引用传递 scoped_ptr 是一种好习惯(从一个方法到另一个类中的方法)?
【发布时间】:2010-03-21 19:19:04
【问题描述】:

或者如果我需要这样做,那么我应该只使用 shared_ptr 吗?

【问题讨论】:

    标签: c++ pass-by-reference shared-ptr scoped-ptr


    【解决方案1】:

    如果被调用者不需要存储包装的指针,则通过引用传递scoped_ptr 是安全的,只需使用它来调用一些方法。由scoped_ptr 保护的对象将在超出范围时被销毁 - 如果指针是堆栈变量,则在调用函数的末尾,或者当包含的类实例被释放时,如果它是成员变量。

    一般来说,智能指针是用来管理对象所有权的,所以这里有一个简短的介绍:

    • boost::scoped_ptr 将受保护对象的生命周期限制在封闭范围内,只有一个所有者。
    • std::auto_ptr 一次也只有一个所有者,但它允许通过赋值(作为函数参数或返回值)传递所有权。
    • boost::shared_ptr 通过引用计数支持共享所有权,只有当引用计数变为零时,受保护的对象才会被销毁。这是最通用的智能指针,但也是最昂贵的,因为它会承受一些较小的开销(引用计数由原子操作维护,这相当昂贵。)还有循环依赖的可能性。
    • boost::weak_ptr 是一个 非拥有 智能指针,它可以在运行时升级到 boost::shared_ptr,并检查受保护的对象是否仍然存在。

    还有像 boost::shared_array 这样的数组变体,因为 C++ 对单个对象和多个对象具有单独的释放函数(operator deleteoperator delete[]。)

    智能指针支持 Resource Acquisition Is Initialization 或 RAII 习语,这是提供 exception safety guarantees 的一种方式。

    【讨论】:

    【解决方案2】:

    是的,您可以通过引用传递它。

    但是,如果函数只想使用托管对象,您可以考虑传递对对象本身的引用。

    void foo(const boost::scoped_ptr<Object>& o)
    {
         o->foobar();
    }
    
    void bar(const Object& o)
    {
         o.foobar();
    }
    

    不同之处在于,在第一种情况下,您将函数与特定的智能指针类型耦合。

    Object o;
    boost::scoped_ptr<Object> scoped(new Object);
    boost::shared_ptr<Object> shared(new Object);
    
    foo(o);  //no
    foo(scoped); //OK
    foo(shared); //no
    
    bar(o);  //OK
    bar(*scoped); //OK
    bar(*shared); //OK
    

    通常我只会传递scoped_ptr,如果打算对scoped_ptr 实例本身做一些事情(例如释放或重置资源)。 shared_ptr 也是如此(例如,函数希望与其他共享指针共享资源)。

    【讨论】:

      【解决方案3】:

      我个人几乎在所有地方都通过 const 引用传递 shared_ptr。正如其他人所说,如果您正在调用一个函数并传递一个 const 引用,那么调用者几乎肯定会将 shared_ptr 保持在范围内。

      真正的好处是您可以节省以这种方式更新引用计数器的成本。快速阅读 wiki http://en.wikipedia.org/wiki/Reference_counting,您将了解到在引用计数器上不断执行 +1 / -1(可能是原子)操作会破坏您的缓存。

      【讨论】:

        猜你喜欢
        • 2017-06-14
        • 2016-12-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-05-03
        • 2013-01-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多