2

我应该如何避免将“this”指针与智能指针一起使用?是否有任何设计模式/一般建议来解决这个问题?

我假设将两者结合起来是不行的,因为:

  1. 您将本机指针传递给智能指针管理的对象,这首先破坏了使用智能指针的意义,
  2. 如果您在使用时将“this”指针包装在智能指针中,例如“return CSmartPtr(this);”,则您已经有效地设置了多个智能指针来管理同一个对象,因此第一个引用计数为零的指针将从另一方下方摧毁该物体,或
  3. 如果您有一个保存 CSmartPtr(this) 值的成员变量在这些情况下返回,它最终将是一个循环引用,导致引用计数始终为 1。

为了提供一些背景信息,我最近了解了将 STL 容器与对象组合的负面影响(重复浅拷贝、使用基类容器时的切片等),因此我将代码中的一些用法替换为指向对象的智能指针。一些对象使用“this”指针传递对自身的引用,这就是我卡住的地方。

我发现智能指针+“this”被认为是有害的?问了一个有点类似的问题,但答案没有用,因为我没有使用 Boost。

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

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

3 回答 3

2

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

于 2009-09-02T00:10:53.137 回答
2

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

  1. 您刚刚创建了对象(通过new
  2. 您从某个外部方法调用中传递了对象,其中语义显然是所有权之一(例如add容器类)
  3. 对象被传递给另一个线程

只要您遵守规则,并且您没有任何模糊的所有权情况,那么就不应该出现问题。

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

  1. 您将本机指针传递给智能指针管理的对象,这首先破坏了使用智能指针的意义

在这种情况下,由于您正在传递本机指针,您可以按照我的规则假设您没有转移所有权,因此您不能将其转换为智能指针

  1. 如果您在使用时将“this”指针包装在智能指针中,例如“return CSmartPtr(this);”,则您已经有效地设置了多个智能指针来管理同一个对象,因此第一个引用计数为零的指针将从另一个人的下方摧毁对象

这显然是非法的,因为您已经说过该对象已由其他一些智能指针拥有。

  1. 如果您有一个保存 CSmartPtr(this) 值的成员变量在这些情况下返回,它最终将是一个循环引用,导致引用计数始终为 1。

close()如果某些外部代码隐式拥有该成员变量,这实际上是可以管理的——该代码可以在对象被释放之前的某个时间点调用某种方法。显然,经过反思,外部代码拥有该对象,因此它本身应该有一个智能指针。

boost 库(我接受你说你没有使用它)使这类问题更容易管理,因为它按照不同的所有权类型(范围、共享、弱等)划分了智能指针库。

于 2009-09-02T00:12:41.327 回答
1

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

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

于 2009-09-02T07:51:52.237 回答