C++ 将共享指针传递给非所有者函数时的最佳实践是什么?

C++ 将共享指针传递给非所有者函数时的最佳实践是什么?,c++,pointers,C++,Pointers,由于使用共享指针,我经常在希望将它们传递给不(必须)拥有对象的函数的情况下运行。因为我知道对象在函数调用期间是有效的,所以我有四个传递指针的选项: 按价值 参照 弱指针 原始指针 起初,我开始大量使用弱指针(因为我已经有了它们),但是一直锁定它们的开销很烦人,会影响性能。现在我考虑通过引用传递原始指针或共享指针。是否有最佳实践 生命周期由堆栈保证。如果您要传递一个弱\u ptr,那么该函数无论如何只需要获取一个共享的\u ptr 您希望通过值传递原始指针,或者通过引用传递实际对象 这两个选项之间

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

  • 按价值
  • 参照
  • 弱指针
  • 原始指针

  • 起初,我开始大量使用弱指针(因为我已经有了它们),但是一直锁定它们的开销很烦人,会影响性能。现在我考虑通过引用传递原始指针或共享指针。是否有最佳实践

    生命周期由堆栈保证。如果您要传递一个
    弱\u ptr
    ,那么该函数无论如何只需要获取一个
    共享的\u ptr

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


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

    我建议通过
    const std::shared\u ptr&
    传递它们。这有两个好处:

  • 引用计数不会产生开销(默认情况下,引用计数不会增加)
  • 如有必要,该函数可以自由复制共享指针
  • 我经常在它们可能(也可能不是)是线程切换的情况下使用它。例如:

    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(); });
       }
    };
    
    struct Foo{void bar(){};
    类BaseImpl
    {
    公众:
    void CallBar(const std::shared_ptr&f);
    {
    do_call__bar(f);
    }
    私人:
    虚拟无效的调用条(const std::shared\u ptr&f)=0;
    };
    类DerivedDirectCall:public BaseImpl
    {
    虚拟void do_call_bar(const std::shared_ptr&f)覆盖
    {
    f->bar();
    }
    };
    类DerivedAsyncCall:public BaseImpl
    {
    虚拟void do_call_bar(const std::shared_ptr&f)覆盖
    {
    //假设调用传递了这个消息
    //异步完成
    调用([f](){f->bar();});
    }
    };
    
    根据实现是
    DerivedDirectCall
    还是
    DerivedAsyncCall
    ,只有在必要时才会复制共享指针

    此外,上面的评论链接。我想澄清的是,我的答案是关于传递智能指针本身的。如果您知道生命周期不一定会延长,那么最好通过引用传递指向的对象(或原始指针,但只需要允许
    nullptr
    参数)

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

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

    void my_func(int&x);
    int main()
    {
    共享\u ptr demo\u ptr=使\u共享(5);
    my_func(*demo_ptr);
    }
    
    可能的重复请参见@Jeff的问题3如何从
    共享的\u ptr
    获得
    唯一的\u ptr
    ?@Jeff我同意。但是您仍然无法将
    共享的\u ptr
    传递给一个需要
    唯一的\u ptr
    的函数,因此它无法解决如何将
    共享的\u ptr
    传递给函数的问题。@Jeff:我不认为智能指针在提取裸指针时会失去作用,因为对象仍然是受管理的。尤其是当一个函数根本不关心所有权的时候。
    void my_func(int &x);
    
    int main()
    {
        shared_ptr<int> demo_ptr = make_shared<int>(5);
        my_func(*demo_ptr);
    }