2010-05-03 1 views
2

Я помню, как раньше встречался этот концепт, но не могу найти его сейчас в Google.Как подключить boost :: shared_ptr (или другой умный указатель) к счетчику счетчика родителя объекта?

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

class A { 
    B b; 
}; 

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

+0

Почему вы хотите это сделать? –

+0

@Marcelo Cantos, примером может служить обработка сообщений по TCP-соединению: для чтения из сокета вам необходимо предоставить непрерывный буфер, но вы хотите иметь возможность работать с дискретными сообщениями (ставить их в очередь, передавать их). Таким образом, вы можете делать лишние копии сообщений (занимает в два раза больше памяти, может вызвать фрагментацию), или вы можете пересчитать буфер в каждом shared_ptr каждого сообщения (если каждое сообщение является POD и отображается непосредственно в какое-то место в буфере). Таким образом, буфер будет удален (или возвращен в пул и т. Д.), Когда shared_ptr последнего сообщения будет уничтожен. –

+0

PS То есть, если вы не можете держать shared_ptr в буфере в сообщении из-за того, что он должен быть типом POD. –

ответ

5

D'oh!

Нашли это правильно в документации shared_ptr. Это называется псевдонимом (см. section III of shared_ptr improvements for C++0x).

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

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

Который работает, как это (вам нужно построить shared_ptr для родителей первым):

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

Я никогда не знал об aliasing - спасибо за большой совет –

+0

@StephenNutt Даже преобразование 'shared_ptr' в производный класс в базовый класс включает в себя aliasing. – curiousguy

1

Я не тестировал это, но вы должны иметь возможность использовать custom deallocator object, чтобы поддерживать 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)); 
Смежные вопросы