【问题标题】:Temporary pointer before releasing?释放前的临时指针?
【发布时间】:2020-05-08 22:11:49
【问题描述】:

我查看了atlbase.h 以了解CComPtr<> 是如何实现的,并偶然发现了基类CComPtrBase<> 中的Release() 函数,它像这样释放底层对象:

// Release the interface and set to NULL
void Release() throw()
{
    T* pTemp = p;
    if (pTemp)
    {
        p = NULL;
        pTemp->Release();
    }
}

我的智力还不够好,看不出这个临时指针pTemp的意义何在?

为什么这段代码不只是:

   void Release() throw()
   {
       if (p)
       {
           p->Release();

           // EDIT:
           p = NULL;
       }
   }

现在如果你看一下析构函数,析构函数的定义就像我对上面示例的期望一样,有什么区别?

【问题讨论】:

  • 第二个版本没有为一件事设置p = NULL;
  • 啊,好的,我已经编辑过了,但问题还是一样。
  • 在两个线程同时调用 Release() 时使其安全。内存屏障在实现的 Release 函数中。
  • 这不能防止并发访问,因为 p 的获取和清空不是互锁的。它保护的是可重入访问。

标签: c++ pointers com smart-pointers


【解决方案1】:

这里有两种可能的解释:

  1. 如果p->Release() 抛出,那么在第二个变体中它不会被设置为NULL,而在第一个变体中它会。请注意,封闭函数声明为throw(),因此它不应引发异常。此函数可能是在添加 throw() 说明符之前编写的。 (或者,编码员可能习惯于在这种情况下进行防御性编码并使用一种常见的模式。)
  2. 第一个变体可以进行尾调用优化,而第二个则不能。

【讨论】:

    猜你喜欢
    • 2014-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-07
    • 1970-01-01
    • 2016-05-08
    • 1970-01-01
    相关资源
    最近更新 更多