将共享指针传递给非拥有函数时的最佳做法是什么?

时间:2015-07-01 20:30:03

标签: c++ pointers

由于使用共享指针,我经常在我想将它们传递给不需要(必须)拥有该对象的函数的情况下运行。因为我知道在函数调用期间对象是有效的,所以我有四个传递指针的选项:

  1. 按价值
  2. 参考
  3. 弱指针
  4. 原始指针
  5. 起初我开始经常使用弱指针(因为我已经有了它们),但是一直锁定它们的开销很烦人并且达到了性能。现在我考虑通过引用传递原始指针或共享指针。有最好的做法吗?

3 个答案:

答案 0 :(得分:6)

我建议通过const std::shared_ptr<T>&传递它们。这有两个好处:

  1. 引用计数不会产生任何开销(默认情况下不会增加引用计数)
  2. 如有必要,该函数可以自由获取共享指针的副本
  3. 在他们可能(或可能不)是线程切换的情况下,我经常使用它。例如:

    struct Foo { void bar() {} };
    
    class BaseImpl
    {
    public:
       void CallBar(const std::shared_ptr<Foo>& f);
       {
          do_call_bar(f);
       }
    
    private:
       virtual void do_call_bar(const std::shared_ptr<Foo>& f) = 0;
    };
    
    class DerivedDirectCall : public BaseImpl
    {
       virtual void do_call_bar(const std::shared_ptr<Foo>& f) override
       {
          f->bar();
       }
    };
    
    class DerivedAsyncCall : public BaseImpl
    {
       virtual void do_call_bar(const std::shared_ptr<Foo>& f) override
       {
          // assume invoke passes this off
          // to be done asynchronously
          invoke([f] () { f->bar(); });
       }
    };
    

    根据实现是DerivedDirectCall还是DerivedAsyncCall,只有在必要时才会复制共享指针。

    此外,上面的评论与this article on smart pointers相关联。我想明确一点,我的答案是关于传递智能指针本身。如果您知道生命周期不一定会被扩展,那么最好通过引用(或原始指针传递指向对象,但只允许nullptr参数)。

答案 1 :(得分:4)

  

由于使用共享指针,我经常在我想将它们传递给不需要(必须)拥有该对象的函数的情况下运行。

你的措辞听起来像你的实际所关心的函数是指向的对象,而不是指针。因此,您应该传递对象(通过引用):

void my_func(int &x);

int main()
{
    shared_ptr<int> demo_ptr = make_shared<int>(5);
    my_func(*demo_ptr);
}

答案 2 :(得分:3)

堆栈保证了生命周期。如果您要传递weak_ptr,那么该函数无论如何都必须获得shared_ptr

您希望按值传递原始指针,或者通过引用传递实际对象。

这两个选项之间的选择取决于您调用的函数的语义。如果nullptr是函数的有效参数,则传递原始指针。否则,通过引用传递对象。