Как прикрепить boost :: shared_ptr (или другой умный указатель) к счетчику ссылок родительского объекта? - PullRequest
2 голосов
/ 03 мая 2010

Я помню, как сталкивался с этой концепцией раньше, но сейчас не могу найти ее в Google.

Если у меня есть объект типа A, который непосредственно встраивает объект типа B:

class A {
    B b;
};

Как получить умный указатель на B, e. г. boost::shared_ptr<B>, но использовать счетчик ссылок A? Предположим, что сам экземпляр A выделен в куче, и я могу безопасно получить его общий счет, скажем, enable_shared_from_this.

Ответы [ 2 ]

5 голосов
/ 03 мая 2010

D'ой!

Нашел прямо в shared_ptr документации. Он называется псевдонимом (см. раздел III улучшений shared_ptr для C ++ 0x ).

Мне просто нужно было использовать другой конструктор (или соответствующую reset перегрузку функции):

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

Что работает следующим образом (сначала нужно создать shared_ptr для parent):

#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;
}
1 голос
/ 03 мая 2010

Я не проверял это, но вы должны иметь возможность использовать пользовательский объект освобождения , чтобы сохранить shared_ptr для родителя, пока дочерний элемент все еще необходим. Что-то вроде этого:

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));
...