【问题标题】:C++ - pointer passing questionC++ - 指针传递问题
【发布时间】:2011-03-15 20:57:19
【问题描述】:

有人知道如何通过值或引用传递boost::shared_ptr

在我的平台上(32 位)sizeof(shared_ptr) 等于 8 个字节,看起来我应该通过引用传递它们,但也许有人有其他意见/做了个人资料/类似的事情? p>

【问题讨论】:

    标签: c++ shared-ptr parameter-passing


    【解决方案1】:

    在 C++ 中,根据对象的大小来选择是按值传递还是按引用传递通常是个坏主意。

    部分是因为编译器通常会在传递值上执行复制省略,从而抵消复制值的成本,但主要是因为这两个选项通常表现不同。

    所以选择最能表达你需要做的事情的选项。

    对于shared_ptr,它存在的全部原因是它可以被复制,以便多个对象可以共享指向对象的所有权。如果您从未按值传递shared_ptr,您可能会开始怀疑为什么它是shared_ptr。那么scoped_ptr 可能是更有效的解决方案。

    显然,这并不是说您也应该始终按值传递shared_ptr。只是按值传递是它们的常见用例。

    如果您需要调用者和被调用者共享所有权,请按值传递。如果您不希望被调用者获得任何所有权,请通过引用传递。

    【讨论】:

    • 我看到 MT 代码性能受到严重影响,因为复制智能指针会导致引用计数的原子增量和减量产生大量开销。在一些战略性的地方将按值传递更改为按引用传递使性能从差到好。从那时起,我认为也许传递引用应该是默认值。
    • @sbi:我的意思是,如果您始终通过引用传递shared_ptr,那么首先将其作为shared_ptr 毫无意义。然后你可以完全摆脱 ref 计数器。如果您几乎从不想增加/减少引用计数器,您应该考虑为什么要使用引用计数的智能指针。因此,也许我的观点不是“默认按值传递”,而是“默认为另一种智能指针类型,并在您需要引用计数器时回退到shared_ptr(然后是因为您需要存储多个副本)其中,所以从价值上讲是有道理的)
    • 这似乎是一个好点,尽管我很难想出一种方法来根据它来更改有问题的代码。也许如果它的设计考虑到这一点......
    • "如果你不希望被调用者取得任何所有权,通过引用传递。" 如果你有所有权问题,你为什么还要传递一个智能 ptr而不是原始 ptr?
    【解决方案2】:

    如果可以的话,我会在 shared_ptr 上调用参考。这是因为 shared_ptr 的操作是原子的,因此开销异常高,而且如果调用函数仍然对对象具有强引用,则可能会缓存未命中的增量/减量。

    当然,这并不总是可行的——例如,在容器内或成员变量中,它们需要保存自己的引用。

    正如另一个回答者所说,C++ 中的绝大多数开销都在 con/destructor 中,而不是传递原始位和字节。 shared_ptr 也是如此。

    【讨论】:

      【解决方案3】:

      您可以通过两种方式看到这一点:

      • boost::shared_ptr 是一个对象(应该由 const & 传递)。

      • boost::shared_ptr 为指针建模,应被视为指针。

      它们都是有效的,第二个选项会产生构建和销毁额外实例的成本(除非您正在编写性能关键代码,否则这应该不是大问题)。

      有两种情况应该传值:

      • 当您不确定指针的类型是否保持不变时。也就是说,如果您考虑将来在代码库中将shared_ptr<T> 替换为T*,那么编写typedef shared_ptr<T> TPtr; 并将您的函数定义为void yourfunction(TPtr value) 是有意义的

        在这种情况下,当您更改指针类型时,您只需修改typedef 行。

      • 当您在具有不同生命周期的两个模块之间共享指针时。在这种情况下,您需要确保您有两个智能指针实例,并且这两个实例都会增加指针的引用计数。

      在其他情况下,这是一个偏好问题(除非您正在编写性能关键代码,在这种情况下适用不同的规则)。

      【讨论】:

        【解决方案4】:

        我会通过引用到常量传递shared_ptr。如果按值传递,则进入函数使用计数递增,离开函数递减,这是不必要的开销。

        【讨论】:

        • 如果你这样做,每次对指针的访问都是一个间接的距离。编译器将无法将指针值缓存在寄存器中,因为 shared_ptr 指向的可能会随着时间而改变。 const 关键字没有帮助,它不保证其他线程可以改变指向的对象。
        • @jdv:编译器是单线程的野兽。它不关心其他线程。如果优化确实破坏了多线程,那是你编写线程不佳的代码的错。并且编译器会很高兴地破坏你的线程希望。
        • @Puppy 其他线程不会直接调用,但是你自己的线程可以,除非你只调用“inlinable”函数。
        【解决方案5】:

        我相信 shared_ptr 的本质是它是一个对象,应该通过值传递。我记得,它使用 ctor 和 dtor 自动处理引用计数,因此它知道何时释放指针。

        每当我使用它时,我都会按值传递它。

        【讨论】:

        • “shared_ptr 的本质是它是一个对象”到底是什么意思?
        • @Fred:存在的原因是您可以将其视为对象而不是指针。
        猜你喜欢
        • 1970-01-01
        • 2023-04-09
        • 1970-01-01
        • 2021-07-09
        • 2013-04-03
        • 2020-08-16
        • 2020-04-25
        • 2011-10-12
        • 1970-01-01
        相关资源
        最近更新 更多