我读过article about using boost::intrusive_ptr for managing COM objects。作者展示了一个包装类,它负责调整通常COM语义的智能指针。这是班级:
template <typename T>
class WrapPtr
{
public:
WrapPtr(boost::intrusive_ptr<T>& ref)
: m_ref(ref), m_ptr(0)
{
}
~WrapPtr()
{
// The second parameter indicates that the reference count should not be incremented
m_ref = boost::intrusive_ptr(m_ptr, false);
}
operator T**()
{
return &m_ptr;
}
operator void**()
{
// Some COM functions ask for a pointer to void pointer, such as QueryInterface
return reinterpret_cast<void**>(&m_ptr);
}
private:
T* m_ptr;
boost::intrusive_ptr<T> m_ref;
};
template <typename T>
WrapPtr<T> AttachPtr(boost::intrusive_ptr<T>& ref)
{
return WrapPtr<T>(ref);
}
我不明白的是析构函数。它将丢弃当前的m_ref对象(当然会导致调用Release
),但随后他会分配一个由m_ptr成员构造的新的intrusive_ptr。我不明白为什么在析构函数中需要它,因为Wrapper类持有intrusive_ptr的副本,而不是对它的引用。如果被调用者更改了指向的对象,则在离开析构函数后此更改将丢失。这是一个错误还是我错过了什么?
答案 0 :(得分:1)
在我曾经看过的一个类似的“安全地址”类中,该类有一个intrusive_ptr引用(intrusive_ptr<T>&
),而不是一个实际的对象(intrusive_ptr<T>
)。您发布的课程实际上不会影响客户端的intrusive_ptr。所以看起来代码只是错误:它应该持有对客户端的intrusive_ptr的引用,而不是一个单独的intrusive_ptr对象:
template <typename T>
class WrapPtr
{
private:
T* m_ptr;
boost::intrusive_ptr<T>& m_ref;
...
};
编辑:我忘了回答你的实际问题:)
通过上面的修复,析构函数的作用变得更加清晰:它设置客户端的intrusive_ptr来保存通过调用运算符T ** 设置的指针或 operator void ** 并将其传递给“getter”方法(例如QueryInterface)。