Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Smart Pointer 
:(
    Опции темы
Lazin
Дата 28.1.2008, 16:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



Вот такой вот велосипед я однажды написал...

Код

    /*!
     * Счётчик ссылок
     * Класс предназначен для открытого наследования, 
     * класс потомок должен иметь защищённый конструктор и
     * защищённый деструктор.
     */
    class FRAMEWORK_ENTRY reference_counter
    {
        template <class T>
        friend class reference;

        private:
            /*!счётчик объектов*/
            static unsigned long count;
            /*!счетчик ссылок на объект*/
            unsigned long ReferenceCounter;
        protected:
            //!Конструктор по умолчанию
            reference_counter(): ReferenceCounter(0) {++count;}
            //!Конструктор копий (ничего не делает)
            reference_counter(const reference_counter&) {}
            //!Оператор присваивания (ничего не делает)
            reference_counter& operator = (const reference_counter&) {return *this;}
        
            //!Деструктор
            virtual ~reference_counter() {--count;}
        private:
            //!Захватить объект
            void grab() throw() { ++ReferenceCounter; }
            //!Освободить объект
            bool drop()
            {    if (ReferenceCounter) --ReferenceCounter;
                if (ReferenceCounter == 0) 
                {    delete this;
                    return true;
                }
                return false;
            }
        public:
            //!Получить колличество объектов
            static unsigned long get_created_count() {return count;}
    };

    /*!
     *    Сильный указатель с подсчётом ссылок и семантикой значений
     */
    template <class Class>
    class reference
    {
    protected:
        Class* pointee;
        typedef Class* type_trait;
    public:
        reference() :pointee(0) {}

        reference(Class *p) :pointee(p)
        {    if (pointee) pointee->grab();
        }

        reference(const reference<Class> &ref) :pointee(ref.pointee)
        {    if (pointee) pointee->grab();
        }

        reference<Class>& operator = (const reference<Class>& ref)
        {    if (this == &ref) return *this;
            if (pointee) pointee->drop();
            pointee = ref.pointee;
            if (pointee) pointee->grab();
            return *this;
        }

        ~reference()
        {    if (pointee) pointee->drop();
        }

        Class* operator->() {return pointee;}

        const Class* operator->() const {return pointee;}

        Class& operator* () {return *pointee;}

        const Class& operator* () const {return *pointee;}

        bool operator == (const reference<Class>& rhs) const { return (pointee == rhs.pointee); }

        bool operator != (const reference<Class>& rhs) const { return (pointee != rhs.pointee); }

        bool operator == (const Class* rhs) const { return (pointee == (Class*)rhs); }

        bool operator != (const Class* rhs) const { return (pointee != (Class*)rhs); }

        //!Ф-я преобразует указатель к типу reference<CastType>
        template<typename CastType>
        reference<CastType> cast()
        {    return reference<CastType>((CastType*)pointee);
        }

        //!Ф-я преобразует указатель к типу reference<CastType>
        template<typename CastType>
        operator CastType() const
        {    return CastType(pointee);
        }
    };  

Цитата(sol78 @  28.1.2008,  15:53 Найти цитируемый пост)
Вопрос конкретный :
как мне написать конструктор для SmartPointer, который не дублирует обьекты, т.е. если есть  уже "вася"
нового "вася" быть не должно . И результат его работы : this указывает на существующий  smart pointer
и  counter++;?

отнаследовать от класса reference_counter, а затем работать через класс reference, прикол этого кода в том, что с потомками reference_counter никак иначе, кроме как через смарт поинтер работать нельзя...
PM MAIL Skype GTalk   Вверх
JackYF
Дата 28.1.2008, 16:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

Репутация: 18
Всего: 162



Lazin, мне очень даже с виду понравилось. Какая лицензия у этого исходника? Под GPLv3 можно стырить? smile


--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
Lazin
Дата 28.1.2008, 17:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



Цитата(JackYF @  28.1.2008,  16:38 Найти цитируемый пост)
Под GPLv3 можно стырить?
а это как?

PM MAIL Skype GTalk   Вверх
JackYF
Дата 28.1.2008, 17:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

Репутация: 18
Всего: 162



Цитата(Lazin @  28.1.2008,  16:11 Найти цитируемый пост)
а это как?

ээээ... ну если в трёх словах, ты объявляешься автором данного кода со всеми вытекающими + разрешаешь всему сообществу изменять код как заблагорассудится при условии сохранения твоих авторских прав smile
а так - на http://www.gnu.org/licenses/gpl-3.0.html всё расписано.


--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
Lazin
Дата 29.1.2008, 09:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



Код

/*
    Smart pointer class
    Copyright (C) 2008  Lazin
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
    /*!
     * Счётчик ссылок
     * Класс предназначен для открытого наследования, 
     * класс потомок должен иметь защищённый конструктор и
     * защищённый деструктор.
     */
    class FRAMEWORK_ENTRY reference_counter
    {
        template <class T>
        friend class reference;
        private:
            /*!счётчик объектов*/
            static unsigned long count;
            /*!счетчик ссылок на объект*/
            unsigned long ReferenceCounter;
        protected:
            //!Конструктор по умолчанию
            reference_counter(): ReferenceCounter(0) {++count;}
            //!Конструктор копий (ничего не делает)
            reference_counter(const reference_counter&) {}
            //!Оператор присваивания (ничего не делает)
            reference_counter& operator = (const reference_counter&) {return *this;}
        
            //!Деструктор
            virtual ~reference_counter() {--count;}
        private:
            //!Захватить объект
            void grab() throw() { ++ReferenceCounter; }
            //!Освободить объект
            bool drop()
            {    if (ReferenceCounter) --ReferenceCounter;
                if (ReferenceCounter == 0) 
                {    delete this;
                    return true;
                }
                return false;
            }
        public:
            //!Получить колличество объектов
            static unsigned long get_created_count() {return count;}
    };
    /*!
     *    Сильный указатель с подсчётом ссылок и семантикой значений
     */
    template <class Class>
    class reference
    {
    protected:
        Class* pointee;
        typedef Class* type_trait;
    public:
        reference() :pointee(0) {}
        reference(Class *p) :pointee(p)
        {    if (pointee) pointee->grab();
        }
        reference(const reference<Class> &ref) :pointee(ref.pointee)
        {    if (pointee) pointee->grab();
        }
        reference<Class>& operator = (const reference<Class>& ref)
        {    if (this == &ref) return *this;
            if (pointee) pointee->drop();
            pointee = ref.pointee;
            if (pointee) pointee->grab();
            return *this;
        }
        ~reference()
        {    if (pointee) pointee->drop();
        }
        Class* operator->() {return pointee;}
        const Class* operator->() const {return pointee;}
        Class& operator* () {return *pointee;}
        const Class& operator* () const {return *pointee;}
        bool operator == (const reference<Class>& rhs) const { return (pointee == rhs.pointee); }
        bool operator != (const reference<Class>& rhs) const { return (pointee != rhs.pointee); }
        bool operator == (const Class* rhs) const { return (pointee == (Class*)rhs); }
        bool operator != (const Class* rhs) const { return (pointee != (Class*)rhs); }
        //!Ф-я преобразует указатель к типу reference<CastType>
        template<typename CastType>
        reference<CastType> cast()
        {    return reference<CastType>((CastType*)pointee);
        }
        //!Ф-я преобразует указатель к типу reference<CastType>
        template<typename CastType>
        operator CastType() const
        {    return CastType(pointee);
        }
    };  

 smile 
PM MAIL Skype GTalk   Вверх
JackYF
Дата 29.1.2008, 10:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

Репутация: 18
Всего: 162



Lazin, смеёшься smile) Спасибо, теперь могу забрать к себе в копилку smile


--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
sol78
Дата 29.1.2008, 16:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 366
Регистрация: 7.7.2007

Репутация: 1
Всего: 0



Я просто в тупике
вот один конструктор для SP ни как не продвигается, гляньте плз,

Код

#ifndef _SMART_PTR
#define _SMART_PTR
#include <string>

class SmartPointer
{
    char* buff;
    SmartPointer * next;
    SmartPointer * prev;
    static SmartPointer* head;
    int count;
    SmartPointer* getSPbyValue(const char* buff);
    void addSmartPointer(const char* str);
    void SmartPointer::InitSmartPointer(const char* str);



public:
    SmartPointer(const char* buff=0);// constructor
    SmartPointer(const SmartPointer & sp);//CopyConstructor
    ~SmartPointer(); //Destructor
    
    const char* get_buff();
    bool update(const char* );
};


#endif


вырезаю все остальное еще не написано
Код

#include "SmartPointer.h"

SmartPointer::SmartPointer(const char* str):count(0), buff(0), next(0), prev(0)
{

    if(str){
        this->addSmartPointer(str);
    }
}
void SmartPointer::InitSmartPointer(const char* str)
{
    if(str)
    {
         ++count; //count ==1, is original
         buff=new char[strlen(str)+1];
         strcpy(buff, str);
    }
}





SmartPointer* SmartPointer::head=0;


void SmartPointer::addSmartPointer(const char* str)
{
        SmartPointer* ptr;
        
        if(head==0)
        {
            head=this;
            head->prev=0;
            InitSmartPointer(str);
        }
    
        else
        {
            if((ptr=getSPbyValue(str))!=0)
            { //str exists
                                      //this dolzhen ukazivat' na ptr??
            
                ptr->count++;
            }
            else
            { //str not exists
               head->prev=ptr;
               this->next=head;
               head=ptr;
               InitSmartPointer(str);
            }
        }
}

SmartPointer* SmartPointer::getSPbyValue(const char* buff)
{
    SmartPointer* tmp;
    
    if(SmartPointer::head)
    {
        tmp=SmartPointer::head;
        while(tmp)
        {
            if(strcmp(tmp->buff, buff)==0)
            {
               return tmp;
            }
            tmp=tmp->next;
        }
    }
    return 0;
}




        
             

        


 const char* SmartPointer::get_buff()
 {
     return this->buff;
 }




    




Lazin,  спасибо за класс, но использовать его не могу  токовы требования 
PM MAIL   Вверх
JackYF
Дата 29.1.2008, 17:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

Репутация: 18
Всего: 162



Цитата(sol78 @  29.1.2008,  15:00 Найти цитируемый пост)
SmartPointer::

это в объявлении класса ставить не нужно

Цитата(sol78 @  29.1.2008,  15:00 Найти цитируемый пост)
вот один конструктор для SP ни как не продвигается, гляньте плз,

увы, телепаты не скажут нам, какой это конструктор и что он должен делать...

Это сообщение отредактировал(а) JackYF - 29.1.2008, 17:32


--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
sol78
Дата 29.1.2008, 18:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 366
Регистрация: 7.7.2007

Репутация: 1
Всего: 0



JackYF,  не множечко терпения

Код

//вызов конструктора
SmartPointer ptr("Vasya");
SmartPointer ptr1("Vasya");

в конструкторе:
-вызов ф. addSmartPointer(const char* str)
-там
Код

void SmartPointer::addSmartPointer(const char* str)
{
        SmartPointer* ptr;
        
        if(head==0)
        {
         //Первий сп как узел
            head=this;
            head->prev=0;
            InitSmartPointer(str);
        }
    
        else
        {
            if((ptr=getSPbyValue(str))!=0)// Существует ли точно такой стр
            { //str exists
                                     
            //Тут проблема нужно чтобы this указивал на тот же елемент???
                ptr->count++;
            }
            else
            { //str not exists
               //Строим новий узел и втыкаем его как новую голову
               head->prev=ptr;
               this->next=head;
               head=ptr;
               InitSmartPointer(str);
            }
        }
}


  
с помощью коменариев попробовала обьяаснить...
PM MAIL   Вверх
JackYF
Дата 29.1.2008, 20:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

Репутация: 18
Всего: 162



Цитата(sol78 @  29.1.2008,  17:06 Найти цитируемый пост)
//Тут проблема нужно чтобы this указивал на тот же елемент???

this (как указатель) изнутри самого себя менять нельзя. Создавай новый объект, который уже указывает на нужную строку либо меняй архитектуру.


--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
sol78
Дата 29.1.2008, 20:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 366
Регистрация: 7.7.2007

Репутация: 1
Всего: 0



Проблема видемо в том что я не могу влиять (в необходимой мне степени) на обьект на уровне конструктора,
что остается вернутся с чаго начала?
Не ужели етот вариант тупиковый?
PM MAIL   Вверх
JackYF
Дата 29.1.2008, 20:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

Репутация: 18
Всего: 162



Цитата(sol78 @  29.1.2008,  19:18 Найти цитируемый пост)
Не ужели етот вариант тупиковый? 

Пробуй другие варианты, которые приходят тебе в голову.
Возможно, это создание не одного централизованного списка, а все одинаковые строки хранят отдельные, "свои" списки.



--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
Lazin
Дата 30.1.2008, 11:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



На мой взгляд COW - это как-то так:
Код

String s1 = "111";
String s2 = s1;//копирования не должно происходить
s2 = "222";//создается новая строка
String s3(s2);//копирования не должно происходить


Набросал небольшой пример, как можно это сделать... я использовал код который приводил выше
Здесь конечно все сильно упрощено, но идея должна быть понятна: объекты класса str_buffer содержат непосредственно данные(строки char-ов), объекты класса String - содержат ссылки на объекты str_buffer, при копировании строк, передаче по значению, копирования данных не происходит, копируются только ссылки (класс ссылки - reference) и при изменении количества ссылок на буфер, счетчик ссылок изменяется то-же, при обнулении счетчика ссылок буфер удаляется.
При изменении строки, просто выделяется новый буффер, а старый освобождается (его счетчик ссылок уменьшается на 1), если только одна строка использовала этот буфер он удалится.
Код

//класс - буфер для строки разделяемый между разными объектами
//используется только через "умный указатель"
class str_buffer : public reference_counter
{
char* buf;

  str_buffer(const char* str)
  {
    buf = new char[strlen(str)+1];
    strcpy(buf, str);// или наоборот strcpy(str, buf);)
  }

  ~str_buffer()
  {
    delete[] buf;
  }

public:

  char* get() {return buf;}

  void set(const char* str) {
    delete[] buf;
    buf = new char[strlen(str)+1];
    strcpy(buf, str);// или наоборот strcpy(str, buf);)
  }

   //производящая функция
   reference<str_buffer> make(const char* str) {return new str_buffer(str);}
};

typedef reference<str_buffer> str_buffer_ptr;

//класс - строка, содержит ссылку на буфер со строкой, при копировании просто получает ссылку на новый буффер
//при модификации строки, освобождает старый буфер и создает новый
class String
{
  str_buffer_ptr buffer; // <- буффер для хранения строки - то что должно разделяться между разными объектами String, 
  //по идее это умный указатель с подсчетом ссылок

  //constructor
  String(const char* str) : buffer( str_buffer::make(str) ) {}
  
  String (const String& str) {buffer = str.buffer;}

  String& operator = (const String& str) {buffer = str.bufer; return *this;}

  //read
  const char* c_str() {return buffer.get();}
  //модификация строки
  String& operator = (const char* str) 
  {
     buffer = str_buffer::make(str);//создается новый буфер под строку (даже если строка такая-же как и была)
     return *this;
  }
};

PM MAIL Skype GTalk   Вверх
sol78
Дата 31.1.2008, 16:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 366
Регистрация: 7.7.2007

Репутация: 1
Всего: 0



Lazin, 
до COW у меня еще руки не дошли...
но в принципе идея понятна...
Я заткнулась на счетчике ссылок и не дублиравание обьектов.... smile 
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0589 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.