首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何有效地使用Boost的intrusive_ptr?

如何有效地使用Boost的intrusive_ptr?
EN

Stack Overflow用户
提问于 2012-03-25 08:22:11
回答 2查看 17.8K关注 0票数 11

手动取消引用

我对Boost的侵入式指针有一个问题。这是boolean conversion operator checks x.get() != 0但是,下面的代码在标记点失败。为什么会这样呢?

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

代码语言:javascript
复制
#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;
}

(架构:Darwin10.7,使用-std=c++11测试编译器g++ 4.7和4.6 )

指向指针的引用

在清理了intrusive_ptr<T>的源代码后,我发现析构函数中只有一次对intrusive_ptr_release的调用:

代码语言:javascript
复制
~intrusive_ptr()
{
    if( px != 0 ) intrusive_ptr_release( px );
}

由于T*类型的参数px是一个左值,因此应该可以通过稍微更改intrusive_ptr_release的函数签名将其设置为零

代码语言:javascript
复制
inline void intrusive_ptr_release(T*& p)
{
    if (--p->count == 0u)
    {
        delete p;
        p = 0;
    }
}

直观地说,这个指向指针的指针引用参数应该将调用上下文中的p的左值赋值为0。Bjarne也叫mentions this idiom。但是,断言仍然在标记的行处失败,这一次让我一无所知。

示例用法

我手动引用和取消引用指针的原因是,在将原始指针传递给C时,我必须使用它一段时间。这意味着我必须在将它传递给C API之前引用它,以防止破坏,并在我取回它时从原始指针重新创建一个介入式指针。下面是一个示例:

代码语言:javascript
复制
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);
}

在这里,在g()中构造y的第二个参数避免了从C API获取指针时的引用,这补偿了f()中的手动引用。

我意识到手动取消引用侵入式指针可能会导致意外的行为,而这种用法似乎没有问题。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-03-26 15:59:06

问题是:为什么你希望x在最后转换为false?你正在以意想不到的方式摆弄裁判计数器!即使仍然有一个指向该对象的intrusive_ptr -x-,您也会将它减少到零。这不是它的工作方式。引用计数器应该至少与指向引用计数对象的intrusive_ptr对象的数量一样大-否则它就不是引用计数器了,不是吗?

票数 13
EN

Stack Overflow用户

发布于 2012-03-25 08:42:07

阅读intrusive_ptr上的文档,我发现使用自己的术语“销毁”对象与指针为0之间没有任何联系。因此,如果你想使用x && x->foo()的习惯用法,你的intrusive_ptr_release函数也应该将指针设置为0

我可以在intrusive_ptr中看到设计决策。当调用intrusive_ptr_release时,应该只执行销毁,不包括delete提供的行为以外的任何其他行为,所以如果您还想将指针放到0以支持该习惯用法,则必须在该函数的代码中执行此操作,但intrusive_ptr本身不会强制您包含比delete本身更多的限制:也就是说,它不会强制您将指针重置为0

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9856893

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档