如何将 boost::shared_ptr (或另一个智能指针)附加到对象父对象的引用计数器?

发布于 2024-08-31 05:43:33 字数 319 浏览 5 评论 0原文

我记得以前遇到过这个概念,但现在在谷歌中找不到它。

如果我有一个 A 类型的对象,它直接嵌入一个 B 类型的对象:

class A {
    B b;
};

我怎样才能有一个指向 B 的智能指针,例如 boost::shared_ptr ,但是使用 A 的引用计数?假设 A 的实例本身是堆分配的,我可以使用 enable_shared_from_this 安全地获取其共享计数。

I remember encountering this concept before, but can't find it in Google now.

If I have an object of type A, which directly embeds an object of type B:

class A {
    B b;
};

How can I have a smart pointer to B, e. g. boost::shared_ptr<B>, but use reference count of A? Assume an instance of A itself is heap-allocated I can safely get its shared count using, say, enable_shared_from_this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

吾性傲以野 2024-09-07 05:43:33

噢!

shared_ptr 文档中找到了它。这称为别名(参见 shared_ptr 的第 III 节C++0x 的改进)。

我只需要使用不同的构造函数(或相应的 reset 函数重载):

template<class Y> shared_ptr( shared_ptr<Y> const & r, T * p );

其工作原理如下(您需要首先构造共享指针到父级):

#include <boost/shared_ptr.hpp>
#include <iostream>

struct A {
    A() : i_(13) {}
    int i_;
};

struct B {
    A a_;
    ~B() { std::cout << "B deleted" << std::endl; }
};

int
main() {
    boost::shared_ptr<A> a;

    {
        boost::shared_ptr<B> b(new B);
        a = boost::shared_ptr<A>(b, &b->a_);
        std::cout << "ref count = " << a.use_count() << std::endl;
    }
    std::cout << "ref count = " << a.use_count() << std::endl;
    std::cout << a->i_ << std::endl;
}

D'oh!

Found it right in shared_ptr documentation. It's called aliasing (see section III of shared_ptr improvements for C++0x).

I just needed to use a different constructor (or a corresponding reset function overload):

template<class Y> shared_ptr( shared_ptr<Y> const & r, T * p );

Which works like this (you need to construct shared_ptr to parent first):

#include <boost/shared_ptr.hpp>
#include <iostream>

struct A {
    A() : i_(13) {}
    int i_;
};

struct B {
    A a_;
    ~B() { std::cout << "B deleted" << std::endl; }
};

int
main() {
    boost::shared_ptr<A> a;

    {
        boost::shared_ptr<B> b(new B);
        a = boost::shared_ptr<A>(b, &b->a_);
        std::cout << "ref count = " << a.use_count() << std::endl;
    }
    std::cout << "ref count = " << a.use_count() << std::endl;
    std::cout << a->i_ << std::endl;
}
星軌x 2024-09-07 05:43:33

我还没有对此进行测试,但您应该能够使用

template<typename Parent, typename Child>
class Guard {
private:
   boost::shared_ptr<Parent> *parent;
public:
   explicit Guard(const boost::shared_ptr<Parent> a_parent) {
      // Save one shared_ptr to parent (in this guard object and all it's copies)
      // This keeps the parent alive.
      parent = new boost::shared_ptr<Parent>(a_parent);
   }
   void operator()(Child *child) {
      // The smart pointer says to "delete" the child, so delete the shared_ptr
      // to parent. As far as we are concerned, the parent can die now.
      delete parent;
   }
};

// ...

boost::shared_ptr<A> par;
boost::shared_ptr<B> ch(&par->b, Guard<A, B>(par));

I have not tested this, but you should be able to use a custom deallocator object to keep a shared_ptr to the parent around as long as the child is still needed. Something along these lines:

template<typename Parent, typename Child>
class Guard {
private:
   boost::shared_ptr<Parent> *parent;
public:
   explicit Guard(const boost::shared_ptr<Parent> a_parent) {
      // Save one shared_ptr to parent (in this guard object and all it's copies)
      // This keeps the parent alive.
      parent = new boost::shared_ptr<Parent>(a_parent);
   }
   void operator()(Child *child) {
      // The smart pointer says to "delete" the child, so delete the shared_ptr
      // to parent. As far as we are concerned, the parent can die now.
      delete parent;
   }
};

// ...

boost::shared_ptr<A> par;
boost::shared_ptr<B> ch(&par->b, Guard<A, B>(par));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文