我喜欢 Boost 的smart_ptr功能以及与shared_ptr
和weak_ptr
之间的转换能力,但由于引用计数不包含在指向类本身中,因此以下代码不起作用(也不应该)。
A *a = new A;
shared_ptr<A> aPtr1(a);
{
shared_ptr<A> aPtr2(a);
// The reference counts of aPtr1 and aPtr2 are both 1.
} // At this point, `a` is destructed by aPtr2.
aPtr1->foo(); // And... SIGTERM
我相信 JUCE 框架具有此功能。[ReferenceCountedObject
和ReferenceCountedObjectPtr
] 但是,我宁愿将Boost用于我的应用程序。是否可以允许 Boost smart_ptrs在指向类而不是私有boost::detail::shared_count
实例中查找引用计数?
简单的解决方案:
A *a = new A;
shared_ptr<A> aPtr1(a);
{
// construct new shared pointer from old one.
shared_ptr<A> aPtr2(aPtr1);
}
aPtr1->foo();
如果您想要更复杂的内容,请参阅 http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html:
标头
<boost/enable_shared_from_this.hpp>
定义类模板enable_shared_from_this
。它用作基类,允许从成员函数中获取对当前对象的shared_ptr
。
编辑:我应该提到enable_shared_from_this
在推导方面有一些不幸的问题。但是,以下内容适用于 c++11;我没有尝试过提升,但我想它也应该在那里工作。我认为这有点黑客;使用 shared_ptr 时使用 RAW 指针注定会以眼泪告终:
struct X : std::enable_shared_from_this {
/* stuff */
};
struct Y : X {
/* stuff */
void yonly() {};
};
int main() {
Y* y = new Y;
shared_ptr<Y> sy(y);
sy->yonly();
{
auto sy2 = std::shared_ptr<Y>(y->shared_from_this(), y);
sy2->yonly();
}
std::cout << "Block ended" << std::endl;
return 0;
}
boost::intrusive_ptr 可能符合您的要求。
但是要注意的是,对于shared_ptr,您应该按如下方式构造它们:
shared_ptr<A> aPtr1 = boost::make_shared<A>();
这不是异常安全的:
// call this as in shared_ptr<T> foo = create_intrusive_shared( new T(blah) );
// This takes ownership of the pointer you pass it.
template<typename T>
std::shared_ptr<T> create_intrusive_shared( T* t )
{
auto retval = std::shared_ptr<T>( t, []( T* cleanup )
{
if (cleanup)
cleanup->RemoveRef();
});
return retval;
}
// Call this if you have an existing instance of T, whose ownership is being
// maintained elsewhere. Do not call it with new T() as an argument, unless
// new instances of T are created with a 0 ref count
template<typename T>
std::shared_ptr<T> make_intrusive_shared( T* t )
{
if (t)
t->AddRef();
auto retval = create_intrusive_shared(t);
return retval;
}
使它们异常安全需要更多的工作。 您需要重新实现make_shared
,但使用清理函数标记生成的shared_ptr
。