Паттерн Singleton (Одиночка)
От: Дмитрий Федоров  
Дата: 14.11.02 08:08
Оценка: 256 (11) +1
Статья:
Паттерн Singleton (Одиночка)
Автор(ы): Дмитрий Федоров
Дата: 14.11.2002


Авторы:
Дмитрий Федоров

Аннотация:
Особенностью Singleton является то, что он гарантирует существование объекта в единственном экземпляре, а самое главное, то, что он создается в тот момент, когда это требуется клиенту. Последующие попытки конструирования объекта приводят лишь к возвращению клиенту ссылки на уже существующий объект, но не к созданию нового.
Как бы так это заделать???
От: konst  
Дата: 11.12.02 16:17
Оценка:
Во первых, статья очень хорошая и полезная, спасибо. Применил в реальной программе я этот сингелтон и остался очень доволен. Но мне надо было несколько изменить поведение исходного класса. У меня ситуация такая: есть клиент, который шлёт запросы на сервер, на сервере есть класс, который создаёт и хранит необходимые для обработки этих запросов таблицы. Но беда в том, что после обработки очередного запроса мне не надо уничтожать объект, т.к. эти запросы идут сериями по многу штук подряд, а удалять объект надо в конце серии... Я сделал во что:

template <class T>
T*  Singleton<T>::Instance()
{
  if(!_self)
  {
    _self=new T;
    _refcount++; // вот это
  }
  _refcount++;
  return _self;
}

Но выглядит на мой взгляд коряво. Может есть какие-то паттерны на этот случай?
Ну, в довесок хочу воткнуть так вот полу-смарт указатель:

template<class T>
class TSingeltonPtr
{
  T *_t;
public:
  TSingeltonPtr() { _t = T::Instance(); }
  ~TSingeltonPtr() { if(_t) _t->FreeInst(); }
  operator T*() { return _t; }
  T* operator->() { return _t; }
  bool operator!() const { return _t==0; }
};

использование:

class Derived : public Singleton<Derived>
{
void foo();
...
};
void bar()
{
  TSingeltonPtr<Derived> sp;
  if ( !sp ) return;
  sp->foo();
}
Маленькое замечание
От: ingie Россия  
Дата: 03.12.02 13:39
Оценка:
Все таки непонятно, откуда пошла дурацкая мода в с++ коде давать данным-членам класса символ подчеркивания в качестве префикса? То есть, и так ясно откуда...
Но ведь c++ не java... Например на MCVC++ код с такими префиксами не компилируется иногда. Ведь сказано же, зарезервировано под надобности компиляторов. Или это специально так отформатировано, чтобы читать было красивее? ;)

А статья действительно хорошая, удивило то что почти не пересекается с [3] ;)
зачем возвращать указатель?
От: Sergeem Израиль  
Дата: 19.11.02 09:56
Оценка:
Еще хочу добавить: почему Instance() возвращает указатель а не ссылку? Тогда и путаницы с delete не будет!
Serge.

Hасколько проще была бы жизнь, если бы она была в исходниках.
взаимодействие синглтонов
От: Sergeem Израиль  
Дата: 19.11.02 09:52
Оценка:
Интересно обсудить эту тему.
Например у меня есть синглтон — менеджер памяти, синглтон — БД-клиент, и т.д.
Тогда менеджер памяти должен "уходить" последним, поскольку другие с-тоны могут освобождать память в своих деструкторах. Интересный вариант есть в loki. Я реалиовал свою модель. феслт кому интересно, могу поделиться или обсудить где-нить в С++ форуме.
Serge.

Hасколько проще была бы жизнь, если бы она была в исходниках.
Просто хотел высказаться, потому как наболело :)
От: the_moon  
Дата: 18.11.02 12:10
Оценка:
Я тоже тут недавно боролся с глобальными методами и классами, в итоге я отказался от глобального класса, а зделал набор интерфейсов который упрятал в namespace. Там же я определил локальные переменные и локальную instance класса switcher, который имеет только конструктор и деструктор и занимается инициализацией и уничтожением внутренних данных функционального набора при запуске-выходе из программы.

типа

myinterface.h
namespace myinterface
{

bool Start();
bool Stop();

bool DoAction();

}


myinterface.cpp
include "myinterface.h"

static struct __Switcher
{
     __Switcher() { constructor(); }
    ~__Switcher() { destructor(); }

} theSwitcher;


static int* InterfaceData;

static void constructor()
{
    InterfaceData = new int(0);
}

static void destructor()
{
    delete InterfaceData;
}

bool myinterface::Start()
{
   //здесь можно принять какието параметры из вне
   //так же можно проверить если другие неоходимые интерфесы 
   //уже запущенны, проинициализированны
}

bool myinterface::Stop()
{
   //(для примера) Мне требовалась остановка потоков без прекращения работы программы
}

bool myinterface::DoAction()
{
    printf( "Hallo from do_action [%d]", InterfaceData++ );
}


То есть мне не надо было заботится об инстансировании глобального объекта, мне почему то показалось жто важным, хотя он и присутсвует тоже.
Снимается проблема со множественным инстансированием.
Проблемы с наследованием практически нет.
Пользователь видит только то, что ему видеть пологается и предлагается.

Конечно не объектно ориентированно, но все-же.
KOPOTbILLIKA KPbIC
И еще нужны дополнения
От: Lexey Россия  
Дата: 15.11.02 08:45
Оценка:
О том, как сделать потокобезопасное создание синглтона. Причем желательно без использования объетов ядра.
Нужны некоторые дополнения
От: Anton V. Kolotaev  
Дата: 15.11.02 08:08
Оценка:
Спасибо за статью.
Однако хотелось бы отметить, что в ней не указан т.н. Meyer's Singleton.
Он более безопасно (имхо) решает проблему удаления одиночки, достаточно прозрачен в реализации, и его я в основном и использую

struct theT 
{
    static T& Instance () {
        static T self;  // здесь можно провести инициализацию связки стат. объектов.
                        // для этого удобно использовать конструктор локального
                        // класса, статическая переменная которого определяется
                        // в этом методе
        return self;
    }
};

Этот прием описан у Александреску в главе 6 Implementing Singletons
Re: Маленькое замечание
От: alexkro  
Дата: 02.03.03 05:55
Оценка:
современная мода — писать подчеркивание в конце переменных: refcount_.
Re: взаимодействие синглтонов
От: odisseyLM  
Дата: 30.01.03 12:12
Оценка:
Слушай, а ты смог ее(Loki) откомпилить в VC?
Re: взаимодействие синглтонов
От: konst  
Дата: 10.12.02 15:27
Оценка:
а выложи на исходники свой вариант
Re: зачем возвращать указатель?
От: null  
Дата: 20.11.02 12:35
Оценка:
Потому, что идея заключается в отказе от применения статических объектов.
Re: И еще нужны дополнения
От: Lostar Россия  
Дата: 17.11.02 19:13
Оценка:
Double-Checked Locking???
С уважением, Николай.
Re: Нужны некоторые дополнения
От: null  
Дата: 15.11.02 09:27
Оценка:
Я знаком с этим типом 'реализации' синглетона, однако не считаю его полноценным синглетоном с точки зрения постановки задачи в начале статьи — возможность управлять временем создания и удаления объекта. В реализации предлагаемой Meyers'ом объект все равно создается и удаляется статически, то есть те проблемы которые описаны в начале статьи статьи остаются в силе. Единственную задачу которую решает данная реализация — это гарантия того, что объект существует в единственном экземпляре, а этого не достаточно.
Re: зачем возвращать указатель?
От: Frostbitten Россия  
Дата: 10.02.03 21:03
Оценка:
А почему он вообще что-то возвращает, да еще "так"?

{
   if (Derived::Instance()->IsReadyToSetCounter())
   {
      Derived::Instance()->SetSomeCouner(
         Derived::Instance()->GetSomeCouner() +1);
   }
}

Очень наглядно... только память куда-то девается :)
Может стоит bool GetInstance(BaseT** pInst) const; ?
Meyers singleton: время создания и удаления
От: Anton V. Kolotaev  
Дата: 15.11.02 14:27
Оценка:
Объект создается при первом обращении и разрушается по выходу и программы.
Гарантируется, что чем позже объект создан, тем раньше он будет разрушен.
Из этого следует, что проблемы возникнут, если в деструкторе одиночка класса A обращается к одиночке класса В, а тот уже разрушен. Это возможно в случае, если одиночка класса В создан позже одиночки класса А... На самом деле интересно, что будет если при закрытии программы после того, как разрушен одиночка B, вызывается деструктор одиночки А, который обращается к одиночке класса В. Будет ли создан заново экземпляр класса В или произойдет сбой?
Re[2]: зачем возвращать указатель?
От: StanislavK Великобритания  
Дата: 28.07.03 08:07
Оценка:
Здравствуйте, null, Вы писали:

N>Потому, что идея заключается в отказе от применения статических объектов.

Какая связь между ссылкой и статическим объектом?
Singleton не должен ни при каких условиях возвращать указатель, дабы не было никаких соблазнов и ошибок.
... << RSDN@Home 1.1 beta 1 >>
Re[2]: Нужны некоторые дополнения
От: Павел Кузнецов  
Дата: 28.07.03 08:56
Оценка:
Здравствуйте, null, Вы писали:

n> Единственную задачу которую решает данная реализация — это гарантия того,

n> что объект существует в единственном экземпляре,

Даже эту задачу данная реализация успешно решает только при условии отсутствия
многопоточности. В это решение корректно синхронизацию добавить весьма проблематично.
Posted via RSDN NNTP Server 1.6 RC1
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re: Паттерн Singleton (Одиночка)
От: Евгений Коробко  
Дата: 03.12.03 11:38
Оценка:
Здравствуйте, Дмитрий Федоров, Вы писали:

Ещё одно дополнение. Для singleton нужно переопределять операторы присваивания и конструктор копирования. Наиболее разумная реакция, на мой взгляд, — генерация исключения. Тогда и проблем с

Singleton s=*Singleton.Instance()

не будет.
Евгений Коробко
Re[2]: Паттерн Singleton (Одиночка)
От: schakal Украина kp.datax.com.ua
Дата: 03.12.03 12:15
Оценка: +2
Ну какая ж это разумная реализация?
Закрытыми их надо делать...


"Евгений Коробко" <12408@news.rsdn.ru> wrote in message news:466069@news.rsdn.ru...
> Здравствуйте, Дмитрий Федоров, Вы писали:
>
> Ещё одно дополнение. Для singleton нужно переопределять операторы присваивания и конструктор копирования. Наиболее разумная реакция, на мой взгляд, — генерация исключения. Тогда и проблем с
>
> Singleton s=*Singleton.Instance()
>
> не будет.
Posted via RSDN NNTP Server 1.8 beta
Re[2]: Паттерн Singleton (Одиночка)
От: PM  
Дата: 03.12.03 12:28
Оценка:
Здраствуйте, Евгений Коробко. Вы писали:

ЕК> Ещё одно дополнение. Для singleton нужно переопределять операторы

ЕК> присваивания и конструктор копирования. Наиболее разумная реакция, на
ЕК> мой взгляд, — генерация исключения. Тогда и проблем с
ЕК>
ЕК> Singleton s=*Singleton.Instance()
ЕК>
ЕК> не будет.
А зачем кидаться исключениями, если можно запретить копирование и присваивание на этапе компиляции?

ps. Странно, что не видел этой статьи раньше
Posted via RSDN NNTP Server 1.7 "Bedlam"
Re[3]: От модератора форума C/C++
От: Павел Кузнецов  
Дата: 03.12.03 12:35
Оценка:
Здравствуйте, schakal, Вы писали:

s> Ну какая ж это разумная реализация?

s> Закрытыми их надо делать...

s> "Евгений Коробко" <12408@news.rsdn.ru> wrote in message news:466069@news.rsdn.ru...

>> Здравствуйте, Дмитрий Федоров, Вы писали:
>>
>> <...>

Ваше сообщение нарушает правила форумов RSDN в отношении оформления и объема цитирования.

Подобный стиль цитирования, т.е. набор нового текста в начале сообщения с последующим
цитированием всего текста оригинального сообщения (top posting) не приветствуется в форумах
RSDN.ru, более того, настоятельно рекомендую не допускать этого в дальнейшем, так как:

Q: Because it reverses the logical flow of conversation.
A: Why is top posting frowned upon?


Ваши читатели будут вам благодарны, если в дальнейшем вы будете цитировать из исходного
сообщения ровно столько, сколько необходимо для понимания контекста вашего ответа, а также
размещать строки своего ответа непосредственно под цитируемыми фрагментами, соответственно
разбивая исходное сообщение. Также считаю нужным обратить ваше внимание на то, что в форумах
RSDN.ru рекомендуется оформлять цитаты, помещая аббревиатуру автора оригинального сообщения
перед символом '>' в начале каждой цитируемой строки.

Плагин для Outlook Express, с легкостью позволяющий это делать, вы можете найти здесь:
http://www.fidolook.com

Более подробно о настройке NNTP клиента для работы с форумами РСДН:
http://www.rsdn.ru/files/progs/rsdnnntp/rsdnnntp.xml

Может быть, лично вам по каким-либо причинам более удобен формат, использованный вами
в своем ответе; также вполне возможно, что вы можете не соглашаться с соображениями,
изложенными выше. Тем не менее, обращаю ваше внимание, что предлагаемый формат сообщений
является именно тем, что предпочитает большинство активных пользователей RSDN.ru, и,
соответственно, тем, чего они ожидают для комфортного чтения. Следуя принятым здесь
обычаям, вы скорее встретите доброжелательно настроенных собеседников, готовых помочь
и пойти навстречу.

Спасибо.
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re: Паттерн Singleton (Одиночка)
От: Кодт Россия  
Дата: 03.12.03 15:40
Оценка: 3 (2)
Здравствуйте, Дмитрий Федоров, Вы писали:

ДФ>Особенностью Singleton является то, что он гарантирует существование объекта в единственном экземпляре, а самое главное, то, что он создается в тот момент, когда это требуется клиенту. Последующие попытки конструирования объекта приводят лишь к возвращению клиенту ссылки на уже существующий объект, но не к созданию нового.


С рождением и смертью синглетона не все так однозначно.

Синглетон создается при первом обращении, затем погибает
— по обнулению ссылок
— по "свистку" (например, по завершению модуля)
После свистка он может быть пересоздан, либо запрещен.

Свисток — это либо выход из программы (код завершения в CRT), либо ручная отмашка.
По ряду причин синглетоны, живущие в DLL, нужно убивать из DllMain(DLL_PROCESS_DETACH), а не из DLL'ского CRT.
Александреску регистрирует функции-убийцы синглетона в atexit(), я предпочитаю определять у синглетона открытый метод-убийцу или делать аналог atexit() с ручным вызовом всей коллекции в DllMain.
typedef void(*my_atexit_fn)(void*);

void schedule_my_atexit(my_atexit_fn fn, void* param); // добавляет функцию в начало списка
void perform_my_atexit(); // вызывает все, что было спланировано



Чтобы не возиться с подсчетом ссылок вручную, указатели на синглетон должны быть умными. Например, так:
template<class T>
class single_holder
{
  friend class single_ptr<T>;

  void addref();
  void release();
  T* take();
  ... all implementation ...
public:
  static single_ptr instance() { return single_ptr(); } // этот метод - дань стилю
};

template<class T>
class single_ptr
{
  typedef single_holder<T> holder;
public:
  single_ptr() { return holder::addref(); }
  single_ptr(const single_ptr&) { return holder::addref(); }
  ~single_ptr() { return holder::release(); }

  operator T*() const { return holder::take(); }
  T* operator->() const { return holder::take(); }
};



Конструкторы (без параметров и копирования) и деструктор синглетона имеет смысл закрывать.
Чтобы single_holder мог работать, нужно объявить его другом.
Конструктор копирования вообще не существует — его объявляют, но не определяют.
class my_single
{
  friend class single_holder<my_single>;

  my_single(const my_single&);

protected: // если допускаем существование наследников
  my_single() { . . . }
  ~my_single() { . . . }

public:
  . . .
};
Перекуём баги на фичи!
Re[2]: Паттерн Singleton (Одиночка)
От: GarikTot  
Дата: 03.12.03 16:22
Оценка:
Здравствуйте, Кодт, Вы писали:

К>По ряду причин синглетоны, живущие в DLL, нужно убивать из DllMain(DLL_PROCESS_DETACH), а не из DLL'ского CRT.

К>Александреску регистрирует функции-убийцы синглетона в atexit(), я предпочитаю определять у синглетона открытый метод-убийцу или делать аналог atexit() с ручным вызовом всей коллекции в DllMain.

Можно об этом подробнее?

К>Конструкторы (без параметров и копирования) и деструктор синглетона имеет смысл закрывать.

К>Чтобы single_holder мог работать, нужно объявить его другом.
К>Конструктор копирования вообще не существует — его объявляют, но не определяют.
К>
К>class my_single
К>{
К>  friend class single_holder<my_single>;

К>  my_single(const my_single&);

К>protected: // если допускаем существование наследников
К>  my_single() { . . . }
К>  ~my_single() { . . . }

К>public:
К>  . . .
К>};
К>


И примерчик использования всего этого хозяйства?

Удалено избыточное цитирование. -- ПК.
Re: Паттерн Singleton (Одиночка)
От: magistr  
Дата: 24.12.04 08:48
Оценка:
Здравствуйте!
У меня такой вот вопрос:
1. Вот тут все говорят, что это плохой сингетон. Где мжно посмотреть на хороший?
2. Как сделать так, чтобы можно было делать наследования такого рода:


class Object:public Singleton<Object>
{
..
private:
   virtual void OnCreate();
..
}


//теперь наследование от класса Object:
class MyObject:public Object
{
..
private:
   MyObject(){}
   virtual void OnCreate()
   {
      MessageBeep(1);
   }
..
}
//проверяем:
MyObject *obj=(MyObject*)MyObject::Instance();
obj->OnCreate(); //не заходит в MyObject


Как сделать так, чтобы можно было так делать?
Я то понимаю, что одиночка был создан ещё при инициализации Object...
Re[2]: Нужны некоторые дополнения
От: Andrew S Россия http://alchemy-lab.com
Дата: 24.12.04 11:34
Оценка:
N>Я знаком с этим типом 'реализации' синглетона, однако не считаю его полноценным синглетоном с точки зрения постановки задачи в начале статьи — возможность управлять временем создания и удаления объекта. В реализации предлагаемой Meyers'ом объект все равно создается и удаляется статически, то есть те проблемы которые описаны в начале статьи статьи остаются в силе.
Ответ неверный.
N>Единственную задачу которую решает данная реализация — это гарантия того, что объект существует в единственном экземпляре, а этого не достаточно.
Аналогично.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[3]: Нужны некоторые дополнения
От: Andrew S Россия http://alchemy-lab.com
Дата: 24.12.04 11:35
Оценка:
n>> Единственную задачу которую решает данная реализация — это гарантия того,
n>> что объект существует в единственном экземпляре,

ПК>Даже эту задачу данная реализация успешно решает только при условии отсутствия

ПК>многопоточности. В это решение корректно синхронизацию добавить весьма проблематично.

Согласен, что синхронизация тут довольно проблематична, впрочем, как и в любом синглтоне. Но решить ее можно, и в соотв. топике форума С++ варинты решений приводились.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[2]: Паттерн Singleton (Одиночка)
От: Аноним  
Дата: 21.03.05 11:04
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Свисток — это либо выход из программы (код завершения в CRT), либо ручная отмашка.

К>По ряду причин синглетоны, живущие в DLL, нужно убивать из DllMain(DLL_PROCESS_DETACH), а не из DLL'ского CRT.
К>Александреску регистрирует функции-убийцы синглетона в atexit(), я предпочитаю определять у синглетона открытый метод-убийцу или делать аналог atexit() с ручным вызовом всей коллекции в DllMain.
К>
К>typedef void(*my_atexit_fn)(void*);

К>void schedule_my_atexit(my_atexit_fn fn, void* param); // добавляет функцию в начало списка
К>void perform_my_atexit(); // вызывает все, что было спланировано
К>


А можно глянуть, как выполняется вызов "всей коллекции в DllMain"? Каждый раз при использовании синглетона в DLL нужно не забыть и вставить цикл в DllMain? А для забывчивых есть какое нибудь средство?
Re: Meyers singleton: время создания и удаления
От: BlackHeretic Израиль  
Дата: 31.03.05 11:07
Оценка:
Здравствуйте, Anton V. Kolotaev, Вы писали:

AVK>Объект создается при первом обращении и разрушается по выходу и программы.

AVK>Гарантируется, что чем позже объект создан, тем раньше он будет разрушен.
AVK>Из этого следует, что проблемы возникнут, если в деструкторе одиночка класса A обращается к одиночке класса В, а тот уже разрушен. Это возможно в случае, если одиночка класса В создан позже одиночки класса А... На самом деле интересно, что будет если при закрытии программы после того, как разрушен одиночка B, вызывается деструктор одиночки А, который обращается к одиночке класса В. Будет ли создан заново экземпляр класса В или произойдет сбой?

Однозначно сбой — такие переменные по определению создаются один раз и повторно созданы не будут.
ICQ 156156278
Re: Паттерн Singleton (Одиночка)
От: ansi  
Дата: 02.04.05 13:16
Оценка: 3 (1)
Статья понравилась. Только есть одно замечание — есть там следующий код:
class SinglImpl: public Singleton
{
protected:
  SinglImpl(){}
  //объявление виртуальным в базовом классе автоматически 
  //дает виртуальность в производном.
  ~SinglImpl() { printf ("~SinglImpl\n"); }
public:
  static Singleton* Instance()
  {
    if(!_self) _self = new SinglImpl();
    _refcount++;
    return _self;
  }
};


Так вот, почему бы вместо двух строк комментария не поставить одно(!) слово virtual? Так на мой взгляд и нагляднее, и понятнее, и копаться в родителях нет надобности (если их много будет)...

Ну и про подчеркивания уже говорили. Я понимаю, что это собственный стиль и каждый его выбирает сам, но он затрудняет чтение, так как человек распознаёт слово целиком, а "_" этому мешает. В данной статье он употреблен грамотно, без злоупотреблений. Но это потому, что членов класса было не много. А вообще, для сравнения:

template <class _Key, class _Value, class _KeyOfValue, 
          class _Compare, class _Alloc> void 
_Rb_tree<_Key,_Value,_KeyOfValue,
  _Compare,_Alloc>::_M_erase(_Rb_tree_node<_Value>* __x)
{
                                // erase without rebalancing
  while (__x != 0) {
    _M_erase(_S_right(__x));
    _Link_type __y = _S_left(__x);
    _Destroy(&__x->_M_value_field);
    this->_M_header.deallocate(__x,1);
    __x = __y;
  }
}


template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
void RbTree <Key, Value, KeyOfValue, Compare, Alloc> :: Erase(RbTreeNode<Value>* x)
{
                                // erase without rebalancing
  while (x != 0) {
    
    Erase( Right(x) );

    LinkType y = Left(x);
    Destroy( &x->ValueField );
        
    this->Header.deallocate(x, 1);

    x = y;

  }
}
new RSDN@Home(1.1.4, 303) << new Message(); std::head::ear << "Celtic Angels — Angels Sea";
Re[2]: Паттерн Singleton (Одиночка)
От: Raurat_Ltd Россия http://cyclone-soft.com
Дата: 02.04.05 16:53
Оценка: :)
Hello, ansi!
You wrote on Sat, 02 Apr 2005 13:16:09 GMT:

a> Ну и про подчеркивания уже говорили. Я понимаю, что это собственный

a> стиль и каждый его выбирает сам, но он затрудняет чтение, так как
a> человек распознаёт слово целиком, а "_" этому мешает. В данной статье он
a> употреблен грамотно, без злоупотреблений. Но это потому, что членов
a> класса было не много. А вообще, для сравнения:

a>
 a> template <class _Key, class _Value, class _KeyOfValue, 
 a>           class _Compare, class _Alloc> void 
 a> _Rb_tree<_Key,_Value,_KeyOfValue,
 a>   _Compare,_Alloc>::_M_erase(_Rb_tree_node<_Value>* __x)
 a> {
 a>                                 // erase without rebalancing
 a>   while (__x != 0) {
 a>     _M_erase(_S_right(__x));
 a>     _Link_type __y = _S_left(__x);
 a>     _Destroy(&__x->_M_value_field);
 a>     this->_M_header.deallocate(__x,1);
 a>     __x = __y;
 a>   }
 a> }
 a>


a> [ccode]

a> template <class Key, class Value, class KeyOfValue, class Compare, class
a> Alloc> void RbTree <Key, Value, KeyOfValue, Compare, Alloc> ::
a> Erase(RbTreeNode<Value>* x) {
a> // erase without rebalancing
a> while (x != 0) {

a> Erase( Right(x) );


a> LinkType y = Left(x);

a> Destroy( &x->ValueField );

a> this->Header.deallocate(x, 1);


a> x = y;


Во блин, это оказвается стиль такой. Я то думал, что разработчики STL в Майкрософте специально так код изгадили, чтобы его читать было нельзя.


With best regards, Alexander. E-mail: fastbrain@hotbox.ru
Posted via RSDN NNTP Server 1.9
Re[3]: Паттерн Singleton (Одиночка)
От: Костя Ещенко Россия  
Дата: 03.04.05 02:35
Оценка:
Raurat_Ltd wrote:

> Во блин, это оказвается стиль такой. Я то думал, что разработчики STL в Майкрософте специально так код изгадили, чтобы его читать было нельзя.


Его изгадили не просто так, а со смыслом. Имена начинающиеся с 2х знаков подчеркивания (__x) или со знака подчеркивания и заглавной буквы (_Key) зарезервированы для использования реализацией стандартной библиотеки во всех контекстах.
Если бы они не использовали зарезервированные имена, то существовала бы вероятность, что некоторое имя из реализации стандартной библиотекии совпадет например с именем пользовательского макроса, и привет.
Posted via RSDN NNTP Server 1.9
На самом деле, люди не читают газеты, они принимают их каждое утро, так же как ванну. ©Маршалл Мак-Льюэн
Re: Паттерн Singleton (Одиночка)
От: Daimond Россия  
Дата: 02.08.05 12:23
Оценка:
Здравствуйте, Дмитрий Федоров, Вы писали:

Спасибо за статью. Понравилась.

Но вопорс возник.

Раздел "Применение шаблонов языка C++"
Там есть такой код (приведу полностью, для понятности):


template <class T>
class Singleton
{
  static T* _self;
  static int _refcount;
protected:
  Singleton(){}
  virtual ~Singleton(){_self=NULL;} // Здесь _self не удаляется
public:
  static T* Instance();
  void FreeInst();
};

template <class T>
T*  Singleton<T>::_self = NULL;

template <class T>
int  Singleton<T>::_refcount=0;

template <class T>
T*  Singleton<T>::Instance()
{
  if(!_self)
    _self=new T;  // Здесь создается объект типа T
  _refcount++;
  return _self;
}

template <class T>
void  Singleton<T>::FreeInst()
{
  if(--_refcount==0)
    delete this;  
    //Почему delete this; ? создавался ведь объект типа T. На мой взгляд delete _self нужно;

}
Re[2]: Паттерн Singleton (Одиночка)
От: Left2 Украина  
Дата: 02.08.05 13:10
Оценка:
[code]
virtual ~Singleton()
[/ccode]

Деструктор виртуальный, значит никаких проблем при удадении по указателю на базовый класс.
... << RSDN@Home 1.1.4 stable rev. 510>>
Re: Паттерн Singleton (Одиночка)
От: k. Россия  
Дата: 02.08.05 15:10
Оценка:
не совсем согласен с подобным удалением синглтона. atexit мне кажется более привлекательной.
... << RSDN@Home 1.1.3 stable >>
Re: Паттерн Singleton (Одиночка)
От: LeeMouse Россия  
Дата: 02.08.05 19:27
Оценка: +1 -1
Здравствуйте, Дмитрий Федоров, Вы писали:

ДФ>Статья:

ДФ>Паттерн Singleton (Одиночка)
Автор(ы): Дмитрий Федоров
Дата: 14.11.2002


ДФ>Авторы:

ДФ> Дмитрий Федоров

ДФ>Аннотация:

ДФ>Особенностью Singleton является то, что он гарантирует существование объекта в единственном экземпляре, а самое главное, то, что он создается в тот момент, когда это требуется клиенту. Последующие попытки конструирования объекта приводят лишь к возвращению клиенту ссылки на уже существующий объект, но не к созданию нового.

Описанная задача исчерпывающе решена очень давно в библиотеке Loki от Андрея Александреску.
При внимательном изучении обоих решений очевидно, что уважаемым автором статьи проделана бесполезная работа
Re: Паттерн Singleton (Одиночка)
От: KBH  
Дата: 03.12.05 13:20
Оценка: :)
Здрасте.

Товарищи, а почему никто не предложил использовать std::auto_ptr для удаления одиночки?

#include <memory>

class Singleton {
private:
  static std::auto_ptr<Singleton> instance;

public:
  static Singleton* getInstance();

};


реализация:

#include "Singleton.h"

std::auto_ptr<Singleton> Singleton::instance; // Инициализируется нулем

Singleton* Singleton::getInstance() {
  if( !instance.get() ) {
    instance = std::auto_ptr<Singleton>(new Singleton());
  }
  return instance.get();
}


Вот и все, теперь при первом обращении создается экземпляр одиночки и уничтожается только при завершении программы.
Re[2]: Паттерн Singleton (Одиночка)
От: Аноним  
Дата: 09.07.07 16:28
Оценка:
Здравствуйте, Кодт, Вы писали:


У кого-нибудь есть рабочий вариант подхода предложеный Кодтом? Мой (который ниже) не компилируется. Поправьте меня или помогите.
template<typename T> class single_ptr;

template<class T> class single_holder {
private:
    static T* _self;
    static int _refcount;
    friend class single_ptr<T>;

    void addref()  {_refcount++;}
    void release();
    T* take();
public:
    //static single_ptr instance() { return single_ptr(); } /*А ЧТО ЗДЕСЬ???*/
};

template<class T> T* single_holder<T>::_self = 0;
template<class T> int single_holder<T>::_refcount = 0;

template<class T>
T* single_holder<T>::take() {
    if(!_self) {
        _self = new T;
    }
    return _self;
}

template<class T>
void single_holder<T>::release() {
    if(--_refcount == 0) {
        delete _self;
    }
}

template<class T>
class single_ptr
{
  typedef single_holder<T> holder;
public:
  single_ptr() { holder::addref(); }
  single_ptr(const single_ptr&) { holder::addref(); }
  ~single_ptr() { holder::release(); }

  operator T*() const { return holder::take(); }
  T* operator->() const { return holder::take(); }
};
Re: Meyers singleton: время создания и удаления
От: superman  
Дата: 12.07.07 07:58
Оценка:
Здравствуйте, Anton V. Kolotaev, Вы писали:

AVK>Объект создается при первом обращении и разрушается по выходу и программы.

AVK>Гарантируется, что чем позже объект создан, тем раньше он будет разрушен.

да ну? и кем же это гарантируется интересно.
Re[2]: Meyers singleton: время создания и удаления
От: Аноним  
Дата: 13.10.08 15:15
Оценка:
Здравствуйте, superman, Вы писали:

S>Здравствуйте, Anton V. Kolotaev, Вы писали:


AVK>>Объект создается при первом обращении и разрушается по выходу и программы.

AVK>>Гарантируется, что чем позже объект создан, тем раньше он будет разрушен.

S>да ну? и кем же это гарантируется интересно.

Стандартом C++.
Re[3]: Meyers singleton: время создания и удаления
От: Кодт Россия  
Дата: 13.10.08 16:36
Оценка: 1 (1) +1
Здравствуйте, <Аноним>, Вы писали:

А>Стандартом C++.


Здрасьте, некропостер.
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Перекуём баги на фичи!
Re[4]: Meyers singleton: время создания и удаления
От: Аноним  
Дата: 13.10.08 16:40
Оценка: -1 :)
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, <Аноним>, Вы писали:


А>>Стандартом C++.


К>Здрасьте, некропостер.


Ну, вопрос не должен оставаться без ответа, и человек может ждет до сих пор (:
Re[2]: Маленькое замечание
От: CreatorCray  
Дата: 14.10.08 08:08
Оценка: +2
Здравствуйте, alexkro, Вы писали:

A>современная мода — писать подчеркивание в конце переменных: refcount_.

Кошмарная мода ИМХО
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[3]: Маленькое замечание
От: oziro Нигерия  
Дата: 18.10.08 12:58
Оценка: :)
Здравствуйте, CreatorCray, Вы писали:

A>>современная мода — писать подчеркивание в конце переменных: refcount_.

CC>Кошмарная мода ИМХО

Согласен. Все знают, что надо писать m_refcount
Re[4]: Маленькое замечание
От: Аноним  
Дата: 20.10.08 08:00
Оценка:
Здравствуйте, oziro, Вы писали:

O>Здравствуйте, CreatorCray, Вы писали:


A>>>современная мода — писать подчеркивание в конце переменных: refcount_.

CC>>Кошмарная мода ИМХО

O>Согласен. Все знают, что надо писать m_refcount


Это не мода, это кодинг-стайл — такое же policy проекта, как соглашение о порядке объявления заголовочныхз файлов, порядок юзания сторонних либ etc. И личным предпочтениям — тут не место.

Одно из проявлений профессионализма — уметь писать два проекта одновременно, с разными кодинг-стайлами
Re[4]: Маленькое замечание
От: CreatorCray  
Дата: 20.10.08 10:53
Оценка:
Здравствуйте, oziro, Вы писали:

A>>>современная мода — писать подчеркивание в конце переменных: refcount_.

CC>>Кошмарная мода ИМХО
O>Согласен. Все знают, что надо писать m_refcount
Наименьшее из зол ИМХО.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.