【问题标题】:Should the "this" pointer and smart pointers be mixed?“this”指针和智能指针是否应该混合使用?
【发布时间】:2009-09-01 23:49:39
【问题描述】:

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

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

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

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

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

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

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

【问题讨论】:

  • 您能否提供示例代码来证明您正在尝试做什么?
  • 我添加了一个人为的例子。我发现很难用代码 sn-p 来描述,但我尽力了。显然,这段代码不是最优的,它旨在最清楚地展示问题。

标签: c++ stl smart-pointers


【解决方案1】:

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

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

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

在你上面的例子中,我可能会这样看:

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

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

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

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

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

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

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-07-02
        • 1970-01-01
        • 2011-03-23
        • 1970-01-01
        • 2016-09-03
        • 1970-01-01
        • 2015-01-24
        相关资源
        最近更新 更多