2012-11-11 34 views
1

我喜欢Boost的smart_ptr功能和转换和从shared_ptrweak_ptr,但由于引用计数不包含在指出的类本身,下面的代码不起作用(和它不应该)。嵌入引用计数与提升shared_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框架有这个功能。 [ReferenceCountedObjectReferenceCountedObjectPtr] 但是,我宁愿使用Boost来申请我的应用程序。是否有可能允许Boost smart_ptrs在指出的类中查找引用计数而不是私有的实例?

+0

看来,我想要的是一个计数的身体/附加智能指针,来自[this](http://www.boost.org/community/counted_body.html)文章。 – Vortico

+0

只需在程序中混合使用智能指针和普通指针,选择一种方法并坚持下去。 – chill

+0

在所有情况下,我都使用'shared_ptr's和'weak_ptr's,但构造函数只能访问原始指针'this'。目前,我无法在构造函数中初始化字段,因此在'a'和'a-> b'之间存在双向关系。 – Vortico

回答

2

简单的解决方案:

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的,势必在眼泪中收场:

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; 
} 
+0

我应该提到我的例子太简单了(与许多SO问题一样)。创建“aPtr2”时,我实际上并没有访问“aPtr1”变量的权限。 不幸的是,'enable_shared_from_this'不适用于我的目的,因为它不能真正支持多态。如果基类也行,派生类不能从'enable_shared_from_this'继承。 – Vortico

+0

@Vortico,是的,在提问时总是很好地解释你已经尝试过并拒绝了哪些解决方案。无论如何,我添加了一些黑客的方式来使用enable_shared_from_this有点多态。 – rici

+0

这是很好的建议。我将在未来做到这一点。\ n 感谢编辑中的示例!我想我会使用该方法,如果它能在Boost shared_ptr上工作的话。 – Vortico

2

boost::intrusive_ptr可能符合您的要求。

但注意到,与shared_ptr的,你应该构建它们如下:

shared_ptr<A> aPtr1 = boost::make_shared<A>(); 
+0

'intrusive_ptr'似乎非常有希望,但是是否支持'weak_ptr'的形式? – Vortico

0

这不是异常安全:

// 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