“this”指针和智能指针应该混合在一起吗?

时间:2009-09-01 23:49:40

标签: c++ stl smart-pointers

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

我假设将两者结合起来是一个禁忌:

  1. 你正在传递一个指向智能指针管理对象的本机指针,它首先打破了使用智能指针的重点,
  2. 如果你在使用时将“this”指针包装在智能指针中,例如“返回CSmartPtr(this);”,你有效地设置了多个管理同一个对象的智能指针,因此第一个引用计数为零的对象会从另一个对象中销毁对象,或者
  3. 如果你有一个成员变量保持CSmartPtr(this)的值在这些情况下返回,它最终将是一个循环引用,导致引用计数总是为1。
  4. 为了给出一些上下文,我最近了解了将STL容器与对象结合起来的负面影响(重复浅层复制,使用基类容器时切片等),所以我在替换它们的一些用法我的代码与智能指针对象。一些对象使用“this”指针传递对自己的引用,这就是我被困住的地方。

    我发现smart pointers + “this” considered harmful?问了一个类似的问题,但答案没有用,因为我没有使用Boost。

    编辑:一个(非常人为的)我正在做的事情的例子是

    ...::AddToProcessingList(vector<CSmartPtr> &vecPtrs)
    {
        vecPtrs.push_back(CSmartPtr(this));
    }
    

3 个答案:

答案 0 :(得分:2)

大多数智能指针框架都提供了一种方法。例如,Boost.SmartPtr提供了一个enable_shared_from_this<T> CRTP类,您可以将其用作基类,然后可以确保共享指针不会产生指向同一对象的两个指针。

答案 1 :(得分:2)

可以将两者结合起来,但是您始终需要清楚地了解所有权问题。通常,我遵循的规则是永远不会将原始指针转换为智能指针(具有所有权),除非您确定在此时获取对象的所有权。这是安全的时间应该是显而易见的,但包括:

  1. 您刚刚创建了对象(通过new
  2. 您从一些外部方法调用传递了对象,其中语义显然是所有权之一(例如add到容器类)
  3. 将对象传递给另一个线程
  4. 只要您遵守规则,并且您没有任何模棱两可的所有权情况,那么就不会出现任何问题。

    在上面的示例中,我可能会按如下方式查看它们:

    1. 你正在传递一个指向智能指针管理对象的本机指针,这个对象在第一时间就失去了使用智能指针的意义
    2. 在这种情况下,由于您传递的是本机指针,您可以根据我的规则假设您没有转移所有权,因此您无法将其转换为智能指针

      1. 如果你在使用时将“this”指针包装在智能指针中,例如“返回CSmartPtr(this);”,你已经有效地设置了多个管理同一个对象的智能指针,因此第一个引用计数为零的对象会从另一个对象中销毁对象
      2. 这显然是非法的,因为你已经说过该对象已经被其他智能指针所拥有。

        1. 如果你有一个成员变量保持CSmartPtr(this)的值在这些情况下返回,它最终将是一个循环引用,导致引用计数总是为1。
        2. 如果某些外部代码隐式拥有成员变量,这实际上可以被管理 - 这个代码可以在对象被释放之前的某个时刻调用某种close()方法。显然在反思时,外部代码拥有对象,所以它本身应该有一个智能指针。

          boost库(我接受你说你没有使用)使这些问题更易于管理,因为它将智能指针库与不同类型的所有权(scoped,shared,weak等)分开)。

答案 2 :(得分:1)

这个问题的一个相当强大的解决方案是使用侵入式智能指针。要实例化RefCountedPtr<T>,T应该来自RefCount。这允许从RefCountedPtr<T>构建this,因为this->RefCount::m_count包含确定生命周期的单个计数器。

下行:当您将对象放入堆栈时,您有一个未使用的RefCount。