C++ 应否";这";指针和智能指针可以混合使用吗?

C++ 应否";这";指针和智能指针可以混合使用吗?,c++,stl,smart-pointers,C++,Stl,Smart Pointers,如何避免将“this”指针与智能指针结合使用?有没有关于解决这个问题的设计模式/一般建议 我认为两者结合是不可能的,因为: 您正在传递一个指向智能指针管理对象的本机指针,该对象首先无法使用智能指针 如果在使用时将“this”指针包装在智能指针中,例如“return CSmartPtr(this);”,则可以有效地设置多个管理同一对象的智能指针,以便第一个引用计数为零的指针将从另一个指针下销毁该对象,或者 在这些情况下,如果有一个成员变量持有CSmartPtr(this)的值以返回,那么它最终将是

如何避免将“this”指针与智能指针结合使用?有没有关于解决这个问题的设计模式/一般建议

我认为两者结合是不可能的,因为:

  • 您正在传递一个指向智能指针管理对象的本机指针,该对象首先无法使用智能指针
  • 如果在使用时将“this”指针包装在智能指针中,例如“return CSmartPtr(this);”,则可以有效地设置多个管理同一对象的智能指针,以便第一个引用计数为零的指针将从另一个指针下销毁该对象,或者
  • 在这些情况下,如果有一个成员变量持有CSmartPtr(this)的值以返回,那么它最终将是一个循环引用,导致引用计数始终为一
  • 为了给大家一点背景知识,我最近了解了将STL容器与对象相结合的负面影响(重复的浅层复制、使用基类容器时的切片等),因此我在代码中用指向对象的智能指针来代替这些用法。一些对象使用“this”指针传递对自身的引用,这正是我遇到的问题

    我发现有人问了一个类似的问题,但答案没有用,因为我没有使用Boost

    编辑:我一直在做的一个(非常做作的)例子是

    ...::AddToProcessingList(vector<CSmartPtr> &vecPtrs)
    {
        vecPtrs.push_back(CSmartPtr(this));
    }
    
    …::AddToProcessingList(向量和向量ptrs)
    {
    向量。推回(CSmartPtr(此));
    }
    
    大多数智能指针框架都提供了一种解决方法。例如,Boost.SmartPtr从这个CRTP类中提供了一个
    enable\u shared\u,您可以使用它作为基类,然后您可以确保您的共享指针不会导致指向同一对象的两个指针。

    可以将这两个指针结合起来,但您始终需要清楚地记住所有权问题。一般来说,我遵循的规则是永远不要将原始指针转换为智能指针(具有所有权),除非您确定在该点上获得了对象的所有权。这样做安全的时间应该是显而易见的,但包括:

  • 您刚刚创建了对象(通过
    new
  • 从某个外部方法调用传递对象,其中语义显然是所有权(例如
    add
    到容器类)
  • 对象正在传递给另一个线程
  • 只要您遵守规则,并且没有任何不明确的所有权情况,那么就不会出现任何问题

    在您上面的示例中,我可能会如下所示:

  • 您正在传递一个指向智能指针管理对象的本机指针,这首先会破坏使用智能指针的意义
  • 在本例中,由于您正在传递本机指针,根据我的规则,您可以假定您没有转移所有权,因此无法将其转换为智能指针

  • 如果在使用时将“this”指针包装在智能指针中,例如“return CSmartPtr(this);”,则可以有效地设置多个管理同一对象的智能指针,以便引用计数为零的第一个指针将从另一个指针下销毁该对象
  • 这显然是非法的,因为您已经说过该对象已经由其他智能指针拥有

  • 在这些情况下,如果有一个成员变量持有CSmartPtr(this)的值以返回,那么它最终将是一个循环引用,导致引用计数始终为一
  • 如果某些外部代码隐式拥有成员变量,则实际上可以管理该变量-此代码可以在释放对象之前的某个点调用某种
    close()
    方法。显然,经过反思,该外部代码拥有该对象,因此它本身应该有一个智能指针


    boost库(我承认您说过您没有使用它)使此类问题更易于管理,因为它将智能指针库划分为不同的所有权类型(作用域、共享、弱等)。

    解决此问题的一个相当健壮的解决方案是使用侵入式智能指针。要实例化
    RefCountedPtr
    ,T应该从RefCount派生。这允许从
    This
    构造
    RefCountedPtr
    ,因为
    This->RefCount::m_count
    保存确定生存期的单个计数器


    缺点:当您将对象放在堆栈上时,您有一个未使用的RefCount。

    您能否提供示例代码作为您尝试执行操作的概念证明?我添加了一个人为的示例。我发现很难用一段代码来描述它,但我尽了最大努力。显然,这段代码不是最优的,它的设计目的是最清楚地展示问题。