Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Организация подсчета ссылок для умного указателя


Автор: azesmcar 23.11.2007, 23:13
Добрый вечер,

Пишу умный указатель, столкнулся с такой вот проблемой.

К примеру
Код

template <class _T>
class smart_ptr
{
public:
    smart_ptr(_T* ptr)
    {
        object = ptr;

        ++ref_count;
    }

    ~smart_ptr()
    {
        --ref_count;
        if (ref_count == 0)
            delete ptr;
    }
private:
    smart_ptr(const smart_ptr& rhl);
    smart_ptr& operator = (const smart_ptr& rhl);
    _T* object;

    static int ref_count;
};


(это далеко не идеальный код умного указателя, просто для примера написал)

и...возьмем к примеру такой вот код в функции main
Код

smart_ptr mc_ptr1(new mc(1)); //представим что есть у нас такой класс mc
smart_ptr mc_ptr2(new mc(2));

в этом случае наш счетчик ссылок будет иметь значение 2, что неверно, ведь mc_ptr1 и mc_ptr2 разные обьекты..несмотря на то что типы у них одинаковые. Следовательно подсчет ссылок организован нерверно. Первое решение пришедшее на ум это использовать std::map. 
Но мне оно не кажеться самым лучшим, почему то не покидает чувство что есть вариант получше. Попробовал посмотреть как реализован boost::shared_ptr, но boost как оказался не блещет обилием понятного кода и решил что лучше спросить у тех кто сталкивался, чем копаться в классах sp_counted_base, sp_counted_impl, sp_counted_base, weak_count итд...

Заранее спасибо

Автор: MAKCim 24.11.2007, 00:00
Код

template <class _T>
class smart_ptr
{
public:
    smart_ptr(_T* ptr)
    {
        object = ptr;
        ref_count = new int(1);
    }

    smart_ptr(const smart_ptr<T>& ref) {
        ref_count = &++*ref.ref.count;
        object = ref.object;
    }

    smart_ptr<T>& operator=(const smart_ptr<T>& ref) {
        destroy();
        ref_count = &++*ref.ref_count;
        object = ref.object;
    }

    ~smart_ptr()
    {
        destroy();
    }
private:
    void destroy() {
        if (!--*ref_count) {
            delete ref_count;
            delete object;
        }
    }

    smart_ptr(const smart_ptr& rhl);
    smart_ptr& operator = (const smart_ptr& rhl);
    _T* object;
    int * ref_count;
};

Автор: archimed7592 24.11.2007, 00:03
Есть несколько способ подсчитывать ссылки.
1. Построение связного списка из уиных указателей(т.о., когда список пуст, память удаляется).
2. Создание динамического счётчика.

Вот простой пример для 2-го случая:
Код

class rc
{
    rc()
        : pc(new int(1))
    { }
    rc(const rc &rhs)
        : pc(rhs.pc)
    {
        ++(*pc);
    }
    rc &operator =(const rc &rhs)
    {
         finalize();
         pc = rhs.pc;
         ++(*pc);
         
         return *this;
    }

    ~rc()
    { finalize(); }
    
    bool last()
    { return *rc == 1; }

private:
    void finalize()
    {
        if (--(*pc) > 0)
            pc.release();
    }

    std::auto_ptr< int > pc;
};

template< typename T >
class sp
{
public:
    sp(T *p)
        : p(p)
    { }
    
    template< class U >
    sp(const sp< U > &rhs)
        : c(rhs.c), p(rhs.p)
    { }
    
    template< class U >
    sp &operator =(const sp< U > &rhs)
    {
        if (c.last())
            delete p;
        
        c = rhs.c;
        p = rhs.p;
    }
    
    ~sp()
    {
        if (c.last())
            delete p;
    }
    
    T *get() const
    { return p; }
    
    // и пр. ф-ции, имитирующие работу указателя
private:
    rc c;
    T *p;
};


ps. Писал здесь, мог облажаться...

Добавлено через 1 минуту и 27 секунд
У MAKCimа код короче, а у меня более повторно используемый smile.

Автор: azesmcar 24.11.2007, 00:14
Цитата

Код

ref_count = &++*ref.ref.count;



ааааа smile вот оно что
Почему то все время на static тянуло smile
остальное уже сам додумаю.

Всем спасибо

Автор: JackYF 24.11.2007, 00:31
Цитата(azesmcar @  24.11.2007,  00:14 Найти цитируемый пост)
Всем спасибо

тему-то закрой ;)

Автор: UnrealMan 24.11.2007, 15:21
Цитата(archimed7592 @  24.11.2007,  00:03 Найти цитируемый пост)
У MAKCimа код короче, а у меня более повторно используемый 

У вас обоих не учтено самоприсваивание.

Автор: archimed7592 24.11.2007, 15:25
Цитата(UnrealMan @  24.11.2007,  15:21 Найти цитируемый пост)
У вас обоих не учтено самоприсваивание. 

Вечно я про это забываю... Спасибо за замечание smile.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)