Удаление статических членов
От: wdm Россия  
Дата: 15.11.05 04:35
Оценка:
Здраствуйте. Помогите разобраться со следующим вопросом:
Имеет место быть такая конструкция:

//...
template <TObject>
class foo{
//...
static std::deque<TObject> TObjectMas;
public:
foo(){}
~foo(){
// что то делаем
}
};
//...
template<> std::deque<TSerialObject * > foo<TSerialObject> TObjectMas;
//....
// где-то в программе
class client{
//...
foo<TSerialOblect * > f;
public:
client(){}
~client(){}
};

//...
При инициализации главной формы (проект на C++ Builder) в её конструкторе
делаем так:
client * c=new client;
Вопрос: Почему при закрытии приложения когда мы добираемся до деструктора
foo::~foo(){} деструктор ~deque уже был вызван и удалил очередь вместе со всем содержимым?

Заранее благодарен за ответы(любые) и извините за сумбурное изложение.
Re: Удаление статических членов
От: Aera Беларусь  
Дата: 15.11.05 07:46
Оценка:
Здравствуйте, wdm, Вы писали:

wdm>//...
wdm>template <TObject>
wdm>class foo{
wdm>//... 
wdm>   static std::deque<TObject> TObjectMas;
wdm>public:
wdm>   foo(){}
wdm>   ~foo(){
wdm>       // что то делаем
wdm>   }
wdm>};
wdm>//...
wdm>template<> std::deque<TSerialObject * > foo<TSerialObject> TObjectMas;
wdm>//....
wdm>// где-то в программе
wdm>class client{
wdm>    //...
wdm>    foo<TSerialOblect * > f;
wdm>public:
wdm>    client(){}
wdm>    ~client(){} 
wdm>};

wdm>//...
wdm>При инициализации главной формы (проект на C++ Builder) в её конструкторе
wdm>делаем так:
wdm>client * c=new client;
wdm>Вопрос: Почему при закрытии приложения когда мы добираемся до деструктора
wdm>foo::~foo(){} деструктор ~deque уже был вызван и удалил очередь вместе со всем содержимым?

Не понятно в какой момент ты делал delete c;, но возможно, что уже после того, как начала отрабатываться уничтожение глобальных переменных. Т.е. вызов кода из деструктора статического экземпляра класса (см ниже) может привести к такому результату
class Temp 
{
 ~Temp()
 {
   delete c; // часть статических переменных уже была уничтожена
 }
};
Temp temp;
--
RedApe
Re: Удаление статических членов
От: Glоbus Украина  
Дата: 15.11.05 07:59
Оценка:
Здравствуйте, wdm, Вы писали:

wdm>При инициализации главной формы (проект на C++ Builder) в её конструкторе

wdm>делаем так:
wdm>client * c=new client;
wdm>Вопрос: Почему при закрытии приложения когда мы добираемся до деструктора
wdm>foo::~foo(){} деструктор ~deque уже был вызван и удалил очередь вместе со всем содержимым?

Кто это "мы"? Не понятно, когда ты вызываешь delete c;. приведи кусочек кода.
Удачи тебе, браток!
Re[2]: Удаление статических членов
От: wdm Россия  
Дата: 15.11.05 08:09
Оценка:
Здравствуйте, Aera, Вы писали:


A>Не понятно в какой момент ты делал delete c;, но возможно, что уже после того, как начала отрабатываться уничтожение глобальных переменных. Т.е. вызов кода из деструктора статического экземпляра класса (см ниже) может привести к такому результату


Деструктор с я вызываю из деструктора главной формы соответственно. Когда писал вопрос я это упустил, извините.
Что касается удаления статических переменных то вопрос можно юыло бы переформулировать след. образом — как управлять последовательностью их уничтожения.
Раньше я делал так:

template <typename T>
class foo{
static T * mas;
static int count;
static void open() { mas=new T; }
static void close() { delete mas; }
foo(){
if(count++==0)open();
}
~foo(){
if(--count==0)close();
}
};

template <> int foo<Object> count=0;
template <> Object * foo<Object> mas=NULL;

и все работало на ура. Но сейчас даже такой прием не помогает. Обьясните дураку как правильно?
Re[2]: Удаление статических членов
От: wdm Россия  
Дата: 15.11.05 08:13
Оценка:
Здравствуйте, Glоbus, Вы писали:

wdm>>При инициализации главной формы (проект на C++ Builder) в её конструкторе

wdm>>делаем так:
wdm>>client * c=new client;
wdm>>Вопрос: Почему при закрытии приложения когда мы добираемся до деструктора
wdm>>foo::~foo(){} деструктор ~deque уже был вызван и удалил очередь вместе со всем содержимым?

G>Кто это "мы"? Не понятно, когда ты вызываешь delete c;. приведи кусочек кода.


Еще раз извиняюсь за неточность в вопросе. delete c вызываю естественно в деструкторе формы.
Re: Удаление статических членов
От: Alex_Avr Россия  
Дата: 15.11.05 09:03
Оценка:
Здравствуйте, wdm, Вы писали:

wdm>Здраствуйте. Помогите разобраться со следующим вопросом:

wdm>Имеет место быть такая конструкция:
wdm>//...
wdm>template <TObject>
wdm>class foo{
wdm>//... 
wdm>   static std::deque<TObject> TObjectMas;
wdm>public:
wdm>   foo(){}
wdm>   ~foo(){
wdm>       // что то делаем
wdm>   }
wdm>};
wdm>//...
wdm>template<> std::deque<TSerialObject * > foo<TSerialObject> TObjectMas;
wdm>//....
wdm>// где-то в программе
wdm>class client{
wdm>    //...
wdm>    foo<TSerialOblect * > f;
wdm>public:
wdm>    client(){}
wdm>    ~client(){} 
wdm>};

Хм, что-то я не понял, выделенное — это определение статической переменной класса?
Мне кажется, что должно быть как-то так:
template <class TObject>
class foo{
    //...
    static std::deque<TObject> TObjectMas;
public:
    foo(){}
    ~foo(){
        // что то делаем        
    }
};
//...

template<class TObject> 
std::deque<TObject> foo<TObject>::TObjectMas;

//....
// где-то в программе
class client
{
    //...
    foo<TSerialObject * > f;
public:
    client(){}
    ~client(){}
};
С уважением, Александр Авраменко.
Re[3]: Удаление статических членов
От: Aera Беларусь  
Дата: 15.11.05 09:42
Оценка:
Здравствуйте, wdm, Вы писали:

wdm>Деструктор с я вызываю из деструктора главной формы соответственно. Когда писал вопрос я это упустил, извините.

wdm>Что касается удаления статических переменных то вопрос можно юыло бы переформулировать след. образом — как управлять последовательностью их уничтожения.

По хорошему никак. Единственный принцип, то, что было инициализировано первым, будет уничтожено последним.

wdm>и все работало на ура. Но сейчас даже такой прием не помогает. Обьясните дураку как правильно?


Можно сделать так:
template<typename T> class foo
{
public:
  // как-бы Singleton, работает только в однопоточной среде
  static std::deque<T>*& deque_ptr_() const
  {
    static std::deque<T>* pointer;
    return pointer;
  }

  // образаться к deque при помощи этой функции
  static std::deque<T>& get_deque()
  {
    if (!deque_ptr_()) 
    {
      deque_ptr_()=new std::deque<>();

      //atexit(&foo::destroy_deque);
      // можно сделать так, но в твоем случае, 
      // это ничего не изменит, поскольку 
      // функция destroy_deque вызовется
      // до удаления большинства статических 
      // переменных, и последующий вызов get_deque() из 
      // какого-либо деструктора приведет к зацикливанию
    }
    return *deque_ptr_();
  }
 
  // необходимо явно вызывать при завершении программы
  // если раскоментировать atexit выше, то явное удаление не требуется
  static void __cdecl destroy_deque() 
  {
    delete deque_ptr_();
    deque_ptr_()=0;
  }

  foo() {}
  ~foo() {}
};
--
RedApe
Re[2]: Удаление статических членов
От: wdm Россия  
Дата: 15.11.05 14:57
Оценка:
Здравствуйте, Alex_Avr, Вы писали:

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


A_A>Хм, что-то я не понял, выделенное — это определение статической переменной класса?

A_A>Мне кажется, что должно быть как-то так:

A_A>template<class TObject> 
A_A>std::deque<TObject> foo<TObject>::TObjectMas;


template<> — это частичная специализация
перед первым использованием статической переменной я должен её проинициализировать что бы под неё была выделене память
если сделать как у тебя подо что память выделяться то будет? тип TObject то не известно что такое.
а тип TSerialObject определен и никаких проблем нет.
Re[3]: Удаление статических членов
От: Aera Беларусь  
Дата: 15.11.05 15:05
Оценка:
Здравствуйте, wdm, Вы писали:

wdm>template<> — это частичная специализация

wdm>перед первым использованием статической переменной я должен её проинициализировать что бы под неё была выделене память
wdm>если сделать как у тебя подо что память выделяться то будет? тип TObject то не известно что такое.
wdm>а тип TSerialObject определен и никаких проблем нет

обратите внимание, что если объявлять вместо статической переменной шаблона класса статическую переменную функции, как сделано здесь
Автор: Aera
Дата: 15.11.05
, то объявлять ничего не нужно и необходимая переменная сама создается при инстацировании класса.
--
RedApe
Re[4]: Удаление статических членов
От: wdm Россия  
Дата: 15.11.05 15:18
Оценка:
Здравствуйте, Aera, Вы писали:

A>обратите внимание, что если объявлять вместо статической переменной шаблона класса статическую переменную функции, как сделано здесь
Автор: Aera
Дата: 15.11.05
, то объявлять ничего не нужно и необходимая переменная сама создается при инстацировании класса.

Хм, не могли бы вы по подробнее разъяснить что происходит в таком случае?
Откровенно говоря для меня подобная конструкция кажется несколько не привычной...не сталкивался как-то....
Re[5]: Удаление статических членов
От: Aera Беларусь  
Дата: 16.11.05 07:13
Оценка:
Здравствуйте, wdm, Вы писали:

wdm>Хм, не могли бы вы по подробнее разъяснить что происходит в таком случае?

wdm>Откровенно говоря для меня подобная конструкция кажется несколько не привычной...не сталкивался как-то....

template<typename T> class foo
{
public:
  // как-бы Singleton, работает только в однопоточной среде
  static std::deque<T>*& deque_ptr_()
  {
    static std::deque<T>* pointer;
    return pointer;
  }

  // образаться к deque при помощи этой функции
  static std::deque<T>& get_deque()
  {
    if (!deque_ptr_()) 
    {
      deque_ptr_()=new std::deque<>();

      //atexit(&foo::destroy_deque);
      // можно сделать так, но в твоем случае, 
      // это ничего не изменит, поскольку 
      // функция destroy_deque вызовется
      // до удаления большинства статических 
      // переменных, и последующий вызов get_deque() из 
      // какого-либо деструктора приведет к зацикливанию
    }
    return *deque_ptr_();
  }
 
  // необходимо явно вызывать при завершении программы
  // если раскоментировать atexit выше, то явное удаление не требуется
  static void __cdecl destroy_deque() 
  {
    delete deque_ptr_();
    deque_ptr_()=0;
  }

  foo() {}
  ~foo() {}
};


Если мы инстацируем класс например foo<int>, то создается функция foo<int>::deque_ptr_() в которой есть статическая переменная pointer. Компилятор автоматически отводит под нее место для каждого типа T. Что-то типа этого:
std::deque<int>* foo<int>::deque_ptr_::pointer=0;

Для того, чтобы управлять временем удаления переменной, создаем не статический эземпляр, а указатель на него. Обращаемся к deque посредством функции get_deque(), что позволяет при первом запуске инициализировать указатель.
--
RedApe
Re[3]: Удаление статических членов
От: Alex_Avr Россия  
Дата: 16.11.05 09:15
Оценка:
Здравствуйте, wdm, Вы писали:

A_A>>template<class TObject>

A_A>>std::deque<TObject> foo<TObject>::TObjectMas;
wdm>[/code]

wdm>template<> — это частичная специализация

wdm>перед первым использованием статической переменной я должен её проинициализировать что бы под неё была выделене память
wdm>если сделать как у тебя подо что память выделяться то будет? тип TObject то не известно что такое.
wdm>а тип TSerialObject определен и никаких проблем нет.

Насколько я знаю, память под статическую переменную шаблонного класса выделяется компилятором
при инстанцировании шаблона для конкретного типа, т.е. в твоем случае, когда ты объявляешь
//...
    foo<TSerialObject *> f;
//...


Что касается синтаксиса объявления статической переменной шаблонного класса, то вот что
говорит по этому поводу стандарт (2003):

14.5.1.3 Static data members of class templates
A definition for a static data member may be provided in a namespace scope enclosing the definition of the
static member’s class template.

[Example:
template<class T> class X {
static T s;
};
template<class T> T X<T>::s = 0;
—end example]


У меня, во всяком случае, приведенный мной пример успешно откомпилировался на VC 7.1 и никаких
проблем с деструктором при его выполнении не возникло.
С уважением, Александр Авраменко.
Re[3]: Удаление статических членов
От: Июнь  
Дата: 16.11.05 14:19
Оценка:
Здравствуйте, wdm, Вы писали:

wdm> template<> std::deque<TSerialObject * > foo<TSerialObject> TObjectMas;


wdm>template<> — это частичная специализация


это не так, это вообще не специализация
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.