如何有效地使用Boost的intrusive_ptr?

mav*_*vam 11 c++ boost memory-management smart-pointers c++11

手动Unref

我对Boost的侵入式指针有一个问题.它是布尔转换运算符检查x.get() != 0.但是,下面的代码在标记点处失败.为什么会这样?

我猜我可能与delete没有设置指针0(或nullptr)的事实有关.如果不是这样,我怎么能有效地使用侵入式指针?我希望能够使用像常规指针这样的侵入式指针,例如,在表达式中x && x->foo(),但这个人工制品似乎排除了它.

#include <atomic>
#include <boost/intrusive_ptr.hpp>

struct T
{
    T() : count(0u) { }

    size_t ref_count()
    {
        return count;
    }

    std::atomic_size_t count;
};

void intrusive_ptr_add_ref(T* p)
{
    ++p->count;
}

void intrusive_ptr_release(T* p)
{
    if (--p->count == 0u)
        delete p;
}

int main()
{
    boost::intrusive_ptr<T> x;
    x = new T;
    assert(x->ref_count() == 1);

    auto raw = x.get();
    intrusive_ptr_add_ref(raw);
    intrusive_ptr_add_ref(raw);
    assert(x->ref_count() == 3);

    intrusive_ptr_release(raw);
    intrusive_ptr_release(raw);
    assert(x->ref_count() == 1);

    intrusive_ptr_release(raw); // Destroys T, ref_count() == 0.
    assert(! x); // Fails.

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

(架构:Darwin 10.7,测试编译器g ++ 4.7和4.6 -std=c++11)

参考到指针

除草了源代码之后intrusive_ptr<T>,我发现intrusive_ptr_release在析构函数中只有一个调用:

~intrusive_ptr()
{
    if( px != 0 ) intrusive_ptr_release( px );
}
Run Code Online (Sandbox Code Playgroud)

由于pxtype 的参数T*是左值,因此可以通过稍微更改以下函数签名将其设置为零intrusive_ptr_release:

inline void intrusive_ptr_release(T*& p)
{
    if (--p->count == 0u)
    {
        delete p;
        p = 0;
    }
}
Run Code Online (Sandbox Code Playgroud)

直观地说,这个指针引用指针参数应该将p调用上下文中的左值分配给0. Bjarne也提到了这个成语.然而,断言仍然在标记线处失败,这次让我无能为力.

示例用法

我手动修改和解释指针的原因是我必须在将原始指针传递给C API时使用一段时间.这意味着我必须在将它传递给C API之前对其进行引用以防止破坏,并在我将其返回时从原始指针重新创建一个侵入式指针.这是一个例子:

void f()
{
    intrusive_ptr<T> x = new T;
    auto raw = x.get();
    intrusive_ptr_add_ref(raw);
    api_in(raw);
}

void g()
{
    T* raw = api_out();
    intrusive_ptr<T> y(raw, false);
    h(y);
}
Run Code Online (Sandbox Code Playgroud)

这里,构造yin中的第二个参数在g()从C API返回指针时避免了ref,这补偿了手动ref f().

我意识到手动不提供侵入式指针会导致意外行为,而这种用法似乎很好.

sel*_*tze 13

问题是:为什么期望x最终转换为false?你以意想不到的方式搞乱了参考柜台!即使仍然存在intrusive_ptr指向对象的-x,您也将它降低到零.这不是它的工作原理.ref计数器应该至少与intrusive_ptr指向ref计数对象的对象数量一样大- 否则它不会是ref计数器,是吗?

  • 把换句话说:一般侵入指针,特别是(也是微软COM指针)`intrusive_ptr`,正常工作时,其所有用户的服从**所有权语义与它的指针**,这些指针是否为C++模板或生C指针.**所有权语义**要求任何**的refcount变化事件只通过指针(原材料或智能)的条件下,由该指针所有权被确定**发生.(在通俗地说,你不要插手你没有自己的东西.)在OP的代码示例中,`(intrusive_ptr)x`是具有对象的某些所有权的人. (3认同)