Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 08.03.2015, 14:34   #11
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

вторая версия из сообщения #3 - счетчик кривой.
Он не сможет шариться. На выброс.
_Bers вне форума Ответить с цитированием
Старый 08.03.2015, 15:46   #12
FIDE
Заблокирован
 
Регистрация: 02.08.2014
Сообщений: 30
По умолчанию

Цитата:
Сообщение от _Bers Посмотреть сообщение
Код:
SmartPointer(const T &obj)
	{
		ptr=obj.ptr;  //<--- WTF ???
		copy=1;
	}
код на выброс.

все не правильно.
А как правильно сделать конструктор копирования?
FIDE вне форума Ответить с цитированием
Старый 08.03.2015, 18:17   #13
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от FIDE Посмотреть сообщение
А как правильно сделать конструктор копирования?
Могу вам показать дизайн моего собственного велосипеда.

Он по крайней мере рабочий.

ПРИМЕЧАНИЕ:
этот велосипед - только на выброс.

я изготавливал его ещё будучи новичком,
и делал это исключительно в образовательных целях.

С точки зрения дизайна использования - он не обладает мощностью своего стандартного аналога, и вообще несколько наивен.

С точки зрения реализации - не расширяемый.
Есть мелкие огрехи.
Он функционален, но не эффективен.
Принцип хранения счетчика объектов можно было бы сделать более оптимально.

В общем, этот код иллюстрирует принцип работы шаристого смарта,
но и только лишь.

Стиль написания кода у меня тогда ещё не выработался,
поэтому - без слез не глянешь))

Итак:

Код:
#ifndef TSharedPointer_h
#define TSharedPointer_h

#define NULL 0
#define NULL_PTR NULL

template<class TypeT>
class TSharedPointer
{
public:
    TSharedPointer();
    TSharedPointer(const TypeT* ptr);
    TSharedPointer(TypeT* &ptr);
    TSharedPointer(const TSharedPointer& istok);
    ~TSharedPointer();
public:
    void Release(); //Освободит Умный указатель от владения объектом 
                    //корректное понижение кол-ва ссылок на объект. 
                    //Если кол-во ссылок на объект станет равным нулю, 
                    //объект будит уничтожен. 
        
    unsigned int IsEmpty(); //вернёт 1 - если указатель пустой. Или 0 - если что-то хранит

    unsigned int GetCounterLink(); //вернёт количество внешних объектов, которые на него ссылаются

    void Input(const TSharedPointer& Istok); //принять совместное право владения объектом от другого умного указателя
                                       //счетчик ссылок увеличиться. Источник не обнулится

    void Input(const TypeT* Object);

    void Input(TypeT* &Object); //принять право владения объектом. 
                                //Источник - указатель, который в конце операции обнулиться (больше не будет владеть объектом)
        
    void Pass(TSharedPointer &Priemnick); //передать право владения другому умному указателю
                                          //счетчик ссылок увеличится. Источник не обнулится

    void PassAndForgot(TSharedPointer &Priemnick); //передать другому умному указателю право владения объектом, 
                                                   //После передачи права владения, отдающий указатель обнулится.

    void InputAndForgot(TSharedPointer &Istok);    //принять право владением объектом. Источник обнулится

    TypeT* operator -> ();  //получить доступ к интерфейсу подопечного объекта.
                            //попытка получить доступ к несуществующему объекту завершиться аварией в рантайме.

    const TypeT* operator -> ()const;

    TypeT& operator* ();    //вернёт ссылку на подопечный объект

    TSharedPointer& operator= (const TSharedPointer& Istok); 
    TSharedPointer& operator= (TypeT* &Istok); 
    TSharedPointer& operator=(const TypeT* Object);
protected:
    TypeT* mp_Pointer;   //настоящий указатель объекта
    int* mp_CounterLink; //здесь хранится количество ссылок на подопечный объект
private:
    void Clear(); //тупо обнулит данные члены
};
(продолжение следует)
_Bers вне форума Ответить с цитированием
Старый 08.03.2015, 18:17   #14
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

(продолжение. все в одном большом h файле)

Код:
#define                _TSharedPointer template<class TypeT>                         TSharedPointer<TypeT>
#define            void_TSharedPointer template<class TypeT> void                    TSharedPointer<TypeT>
#define            uint_TSharedPointer template<class TypeT> unsigned int            TSharedPointer<TypeT>
#define        ref_Type_TSharedPointer template<class TypeT> TypeT&                  TSharedPointer<TypeT>
#define        ptr_Type_TSharedPointer template<class TypeT> TypeT*                  TSharedPointer<TypeT>
#define  const_ptr_Type_TSharedPointer template<class TypeT> const TypeT*            TSharedPointer<TypeT>
#define       this_Type_TSharedPointer template<class TypeT> TSharedPointer<TypeT>&  TSharedPointer<TypeT>


_TSharedPointer::TSharedPointer(): mp_Pointer(NULL_PTR), mp_CounterLink(NULL_PTR){}

_TSharedPointer::TSharedPointer(const TypeT* ptr): mp_Pointer(NULL_PTR), mp_CounterLink(NULL_PTR){ Input(ptr);}
_TSharedPointer::TSharedPointer(TypeT* &ptr): mp_Pointer(NULL_PTR), mp_CounterLink(NULL_PTR){  Input(ptr);}

_TSharedPointer::TSharedPointer(const TSharedPointer& Istok):mp_Pointer(NULL_PTR), mp_CounterLink(NULL_PTR){ Input(Istok); }

_TSharedPointer::~TSharedPointer() {  Release(); }

void_TSharedPointer::Clear() {mp_Pointer=0;    mp_CounterLink=0;}

void_TSharedPointer::Release() 
{   
    if(mp_CounterLink==0)  { return; }
    --(*mp_CounterLink);
    if( (*mp_CounterLink)==0 ) 
    { 
        delete mp_CounterLink; delete mp_Pointer; 
    }
    Clear();
}


void_TSharedPointer::Input(const TypeT* pObject)
{
    if(pObject==0) {   Release(); return;  }

    ASSERT_ME( (mp_Pointer!=pObject), 
        "void_TSharedPointer::Input(const TypeT* pObject)",
              "УГРОЗА! Умный указатель уже содержит объект с таким же адресом, как у источника. Подозрение на программную ошибку на стороне пользователя"); 
    Release();  
    mp_Pointer = const_cast<TypeT*>(pObject);
    mp_CounterLink=new int(1);
}

void_TSharedPointer::Input(TypeT * &pObject)
{
    if(pObject==0) {   Release(); return;  }
    Release(); mp_Pointer = pObject; mp_CounterLink=new int(1);  pObject=NULL_PTR; 
}

void_TSharedPointer::Input(const TSharedPointer& Istok)
{
    if(mp_Pointer==Istok.mp_Pointer)  {  return; }
    Release();
    if(Istok.mp_Pointer==0) { return; }
    mp_Pointer = Istok.mp_Pointer;  mp_CounterLink = Istok.mp_CounterLink;  (*mp_CounterLink)++;
}

void_TSharedPointer::Pass(TSharedPointer& Priemnick)
{
    if(mp_Pointer==Priemnick.mp_Pointer) {  return; }
    Priemnick.Release();
    if(mp_Pointer==0) {   return;  }
    
    Priemnick.mp_Pointer=mp_Pointer;   Priemnick.mp_CounterLink=mp_CounterLink;   (*mp_CounterLink)++; 
}

void_TSharedPointer::PassAndForgot(TSharedPointer& Priemnick) {     Pass(Priemnick);    Release();}
void_TSharedPointer::InputAndForgot(TSharedPointer& Istok){    Input(Istok);    Istok.Release();}

ptr_Type_TSharedPointer::operator -> ()
{    
    CHECK_NULL_PTR_EXIT(mp_Pointer, 
        "ptr_Type_TSharedPointer::operator -> ()", "ОШИБКА! Попытка получить доступ по нулевому указателю");
    return mp_Pointer;    
}

const_ptr_Type_TSharedPointer::operator -> ()const
{
    CHECK_NULL_PTR_EXIT(mp_Pointer, 
        "ptr_Type_TSharedPointer::operator -> ()", "ОШИБКА! Попытка получить доступ по нулевому указателю");
    return mp_Pointer;    
}

ref_Type_TSharedPointer::operator* ()
{
    ASSERT_MESSAGE(WORK_EXIT, (mp_Pointer!=NULL_PTR), 
        "ref_Type_TSharedPointer::operator* ()","ОШИБКА! Попытка получить доступ по нулевому указателю");
    return *mp_Pointer;
}

uint_TSharedPointer::IsEmpty() {  return(mp_Pointer==0); }
uint_TSharedPointer::GetCounterLink() { return *mp_CounterLink; }

this_Type_TSharedPointer::operator= (const TSharedPointer& Istok) { Input(Istok);  return *this; }
this_Type_TSharedPointer::operator= (TypeT* &Istok)               { Input(Istok);  return *this; } 
this_Type_TSharedPointer::operator=(const TypeT* Object)          { Input(Object); return *this; } 

#endif
_Bers вне форума Ответить с цитированием
Старый 08.03.2015, 18:24   #15
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

FIDE, вам нужно обратить внимание,
что счетчик ссылок - тоже указатель.

Вам нужно спросить себя: почему так? Почему он указатель?

Ответ на этот вопрос - это главное,
что нужно понять в устройстве шаред-поинтера.

Все остальное - на самом деле мелочи. дизайнерская косметика.
_Bers вне форума Ответить с цитированием
Старый 08.03.2015, 21:18   #16
pu4koff
Старожил
 
Аватар для pu4koff
 
Регистрация: 22.05.2007
Сообщений: 9,520
По умолчанию

Тестировать умные указатели нужно не когда всё хорошо работает, а когда сыпятся исключено и код писал идиот, ничего не знающий про указатели
pu4koff вне форума Ответить с цитированием
Старый 10.03.2015, 00:25   #17
FIDE
Заблокирован
 
Регистрация: 02.08.2014
Сообщений: 30
По умолчанию

Я кажется понимаю:нужно хранить кол-во копий указателя и когда оно равно 0 удалять объект. Но вопрос, как это делать? Указатели-то могут указывать хоть на 200 разных объектов...Вроде и не трудно но до меня не дойдет как это делать...
FIDE вне форума Ответить с цитированием
Старый 10.03.2015, 02:01   #18
FIDE
Заблокирован
 
Регистрация: 02.08.2014
Сообщений: 30
По умолчанию

Цитата:
FIDE, вам нужно обратить внимание,
что счетчик ссылок - тоже указатель.
Да, вы правы. Наверно это мне нужно понять. Но я лично так и не догадываюсь...Вы не могли бы подсказать?
FIDE вне форума Ответить с цитированием
Старый 10.03.2015, 02:08   #19
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от pu4koff Посмотреть сообщение
Тестировать умные указатели нужно не когда всё хорошо работает, а когда сыпятся исключено и код писал идиот, ничего не знающий про указатели
как то по идиотски звучит.
_Bers вне форума Ответить с цитированием
Старый 10.03.2015, 02:12   #20
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от FIDE Посмотреть сообщение
Да, вы правы. Наверно это мне нужно понять. Но я лично так и не догадываюсь...Вы не могли бы подсказать?
когда вы создаете смарт:

TSharedPointer<int> smart = new int(10);

он аллоцирует счетчик в куче:

mp_CounterLink=new int(1);

куда ложит единичку.

когда он расшаривается с другими смартами, то значение по этому указателю увеличивается.

и там уже двоечка.

при этом другому смарту он просто указатель нацеливает на тот же адрес.

таким образом уже два смарта поинтера знают где находится их общий счетчик.

поэтому любой из них может изменить значение этого счетчика, и это изменение "заметит" его коллега.
_Bers вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Правильна ли такая реализация списка из указателей на базовый класс? Archet Общие вопросы C/C++ 14 18.01.2012 16:08
АТД: Реализация списка с использованием указателей Suslik963 Помощь студентам 1 17.11.2010 10:06
Ищу умных людей по с++ Maver1k[Kiev] Свободное общение 3 24.03.2010 10:22
прошу помощи у умных людей... lesimel C++ Builder 12 21.12.2009 09:09