使用从另一个具体 class 返回的 shared_ptr

Working with shared_ptr returned from another concrete class

我需要访问在不同具体 class 中实现的对象。所以我决定使用std::shared_ptr。我想知道这里使用 std::shared_ptr 是否合适,如果不合适请建议我是否应该使用 std::weak_ptr。到目前为止,我一直在使用原始指针,但现在我决定在我的项目中使用智能指针,但我无法决定我应该在这里使用哪一个。以下代码片段类似于我在我的项目中尝试做的事情。

#include <iostream>
#include <memory>

class data
{
    public:
    data()
    {
        std::cout<<"\n data constructor Called"<<std::endl;
    }
    ~data()
    {
       std::cout<<"\n data destructor Called"<<std::endl;
    }   
    int GetData()
    {
        return val;
    }
    void SetData(int & val)
    {
        this->val = val;
    }
    private:
    int val;
  };

  class sample
  {
     public:
     sample();
     ~sample();
     void GetShared(std::shared_ptr<data> & arg);
     std::shared_ptr<data> sPtr;
  };

  sample::sample()
  {
     sPtr = std::make_shared<data>();
  }

  sample::~sample()
  {
  }

  void sample::GetShared(std::shared_ptr<data> & arg)
  {
     arg = sPtr;
  }

  int main()
  {
      int val = 40;
      sample obj;
      {
          std::shared_ptr<data> temp1;
          obj.GetShared(temp1);
          temp1->SetData(val);
          std::cout<<"\n Data : "<<temp1->GetData()<<std::endl;
      } // Just to understand whether pointer gets deleted if temp1 goes out of scope.

      {
          std::shared_ptr<data> temp2;
          obj.GetShared(temp2);
          val = 20;
          temp2->SetData(val);
          std::cout<<"\n Data : "<<temp2->GetData()<<std::endl;     
      }

      return 0;
  }

shared_ptr 和 weak_ptr 的区别在于 weak_ptr 不会增加对象的引用计数并防止对象被删除。

这有利有弊,如果你在获取指针后进行异步操作,不确定提供数据的对象是否已经销毁,那么你可以使用weak_ptr检查你是否还有访问对象。

如果不是,则保持简单并使用 shared_ptr。

当您没有明确的资源所有者时,您可以使用 shared_pointer 来共享某些资源的所有权。

如果您不知道 objtemp1temp2 完成 data 之前是否超出范围,这将很有用。然而,在这个例子中,很明显 obj 和它持有的 data 对象 比用户长寿。在那种情况下,您也可以 return 普通指针,或者对数据的引用。

使用 shared_pointer(或 weak_pointer)不会给您带来任何好处,只会增加复杂性。

在你的代码中

  sample obj;
  {
      std::shared_ptr<data> temp1;
      obj.GetShared(temp1);
      temp1->SetData(val);
      std::cout<<"\n Data : "<<temp1->GetData()<<std::endl;
  } // Just to understand whether pointer gets deleted if temp1 goes out of scope.

数据不会被删除,因为它指向 obj 持有的东西,它仍然存在。


我认为答案应该取决于 data 对象在其对应的 sample 对象死亡后是否可以存活:

  • 如果是,那么它应该return一个std::shared_ptr
  • 如果没有,那么它应该return一个std::weak_ptr

您有两个问题需要问自己。

1)sample 获取指针的 调用对象 会比 sample 对象长寿吗?

如果不是那么sample应该使用std::unique_ptr和return一个原始指针reference.

2) 如果 调用对象 确实比 sample 对象长寿,是否介意 data 对象先于它被销毁?

If not then return a std::weak_ptr 可用于在使用前测试 data 对象是否仍然存在。

否则 return std::shared_ptr 保证 data 对象与 调用对象.

总结:

如果调用对象不会超过sample对象:

class sample
{
    std::unique_ptr<data> ptr; // UNIQUE (not shared)

    public:

    data* GetData() { return ptr.get(); }
};

如果 调用对象 可能比 sample 对象长寿,但不关心 data 对象是否长寿:

class sample
{
    std::shared_ptr<data> ptr;

    public:

    std::weak_ptr<data> GetData() { return ptr; }
};

如果 调用对象 可能比 sample 对象活得更久,并且需要 data 对象来维持生命:

class sample
{
    std::shared_ptr<data> ptr;

    public:

    std::shared_ptr<data> GetData() { return ptr; }
};