类和子类中的shared_ptr与unique_ptr用法区别

3

我开始使用智能指针,并试图理解最佳用法。我阅读了很多文章,但对以下示例中应该使用哪种智能指针感到困惑。我包含了shared_ptrunique_ptr的示例,以展示我试图实现的内容:

class A
    public:  
        A();
    private:
        unique_ptr<B> ptrB;

    unique_ptr<SomeObject> ptrUnique;
    shared_ptr<SomeObject> ptrShared;

    A::A()
    {
        ptrB(new B());

        ptrUnique(new SomeObject());
        ptrB->PassUnique(ptrUnique);

        ptrShared(new SomeObject());
        ptrB->PassShared(ptrShared);
    }

class B:
    public:
        void PassUnique(unique_ptr<SomeObject> &ptr_unique);
        void PassShared(weak_ptr<SomeObject> &ptr_weak);
        void DoSomething();
    private:
        unique_ptr<SomeObject> ptrUnique;
        weak_ptr<SomeObject> ptrWeak;

    B::PassUnique(unique_ptr<SomeObject> &ptr_unique)
    {
        ptrUnique = ptr_unique;
    } 

    B::PassShared(weak_ptr<SomeObject> &ptr_weak)
    {
        ptrWeak = ptr_weak;
    }

    B::DoSomething()
    {
        ptrUnique->SomeMethod();

        shared_ptr<SomeObject> ptr1 = ptrWeak.lock();
        ptr1->SomeMethod();
    }

SomeObject类可以是任何类。一个很好的例子是数据库句柄,我从父类A传递到多个类(如B),然后从B传递到C(如果存在)。我的问题是,如果我将unique_ptr作为引用传递,那么在B:PassUnique中设置ptrUnqiue = ptr_unique会创建一个副本,这样就不正确了吗?还是应该通过shared_ptr来完成?这对智能指针的理解对我来说很困惑,希望得到澄清。


你不能执行 ptrUnique = ptr_unique.. 所以你的问题似乎有点无效。http://en.cppreference.com/w/cpp/memory/unique_ptr/operator%3D - default
谢谢,我不太确定用法。 - adviner
2个回答

2

好的,这是一个终身难题。您是否需要SomeObjectA更持久?B是否在此上下文之外使用或发送?您必须决定对象何时死亡。如果您认为SomeObject仅存在于此上下文中,则建议将A作为所有者,因为它分配了资源,并且是指向SomeObject的旧裸指针。代码应该如下所示:

class A
   public:  
     A();
   private:
     unique_ptr<B> ptrB;

     unique_ptr<SomeObject> ptrUnique;
};

A::A()
{
  ptrB(new B());

  ptrUnique(new SomeObject());
  ptrB->PassUnique(*ptrUnique);
}

class B:
  pubic:
    void PassUnique(SomeObject& obj);
    void DoSomething();
  private:
    SomeObject* ptrUnique;
};

B::PassUnique(SomeObject& obj)
{
   ptrUnique = &obj;
} 

B::DoSomething()
{
   ptrUnique->SomeMethod();
}

没有所谓的

ptrUnique = ptr_unique;

如果需要在这个结构之外使用和拥有SomeObject,那么像你所做的那样使用std::shared_ptr。你的std::shared_ptr代码没有出现错误。


感谢您对示例的澄清。是的,SomeObject将从A初始化并传递到B。也可能从B传递到C。但始发者始终是A。 - adviner
有没有使用 B::PassUnique(unique_ptr<SomeObject> &ptr_unique) 替代 B::PassUnique(SomeObject& obj) 的好主意? - adviner
我不会建议这样做。为什么呢?因为它不是const类型的,所以你的函数“PassUnique”可能会有问题,并且使用“reset”和“release”函数释放指针。但是通过引用来传递“unique_ptr”的用途非常少,所以我建议简化这个过程,使用“observer_ptr”,但目前还没有这种东西,所以解决方法就是像我的例子一样通过原始指针或引用来传递。 - Guillaume Racicot

0

答案基本上是指在A、B和/或C中指针的生命周期。将其视为范围,[A...a)、[B...b)和[C...c)。如果[B...b)始终在[A...a)内,且[C...c)始终在[B...b)内,则它们具有像俄罗斯套娃一样的层次结构,那么传递ref-to-ptr就可以了。如果范围重叠并且变化很大,因此您无法真正控制最后一个ptr将被销毁并删除对象的位置,则必须使用shared_ptr。


请再仔细阅读问题。原帖作者正在询问一个具体的问题。 - default

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接