Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Шаблон класса для автоматического освобо  (Прочитано 11847 раз)
0 Пользователей и 1 Гость смотрят эту тему.
CTAPOBEP
Постоялец

ru
Offline Offline
Пол: Мужской

« : 12-08-2008 10:15 » 

Первое. Шаблон класса.

Код:
template <class TYPE>
class New
{
   TYPE m_pType;

public:
   New(void) {m_pType=NULL;}
   New(unsigned int num) {m_pType=(TYPE)new char [sizeof(TYPE)*num];}
   New(TYPE arg) {*this=arg;}
   ~New(void) {if (m_pType) delete [] m_pType;}
   TYPE operator= (TYPE arg)
   {
      if (m_pType) delete [] m_pType;
      return m_pType=arg;
   }
   operator TYPE() {return m_pType;}
   TYPE operator->() {return m_pType;}
};


Второе. Как этим пользоваться.

Код:
Вместо char* ch=new char[num];

пишем

New <char*> ch=new char [num]; //или New <char*> ch(num);

а дальше - все, как обычно:

strcpy(ch, "ABCDEFGH");
ch[8]=0x00;

или

ch="HGFEDCBA\n";

или

ch[0]='A';
ch[1]='B';
...
ch[8]='\0'

if (strcmp(ch, "Abc")) ...

ну и т.д.

Вместо delete [] ch; не пишем ничего, само удалится.


Третье. Все это хорошо, но совсем не интересно. Интересно вот что.


Код:
class CTestDlg
{
   New <CButton*> m_Button[50]; // Это вместо CButton* m_Button[50];
   ...


BOOL CTestDlg::OnInitDialog()
{
   ...
   for (int i=0; i<50; i++)
   {
      m_Button[i]=new CButton;
      RECT rect={20, 20+i*60, 200, 20+i*60+50};
      m_Button[i]->Create("Кнопка", WS_VISIBLE|WS_CHILD, rect, this, 1000+i);
   }
   ...
}

void CTestDlg::OnDestroy()
{
   // Теперь это не нужно !!!
   // for (int i=0; i<50; i++) delete m_Button[i];
}


Четвертое. Вопрос. Посмотрите свежим глазом, какие могут быть проблемы при использовании такого класса?

Спасибо за внимание.
« Последнее редактирование: 12-08-2008 11:36 от CTAPOBEP » Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #1 : 12-08-2008 10:40 » 

CTAPOBEP, оберни код тегами [code]...[/code].
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #2 : 12-08-2008 12:10 » 

Смотри в нете шаблон "Умные указатели".
Тест:
ch="HGFEDCBA\n"; Тест не прошел Программа на выполнении упала.
printf("%s", ch); Тест не прошел Программа на выполнении упала.
ch[0]='a'; Тест не прошел. Программа на выполнении упала.
Еше, может быть ситуация, что два разных указателя ссылаются на один и тот же участок памяти. При удалении одного указателя, Второй у тебя станет не валидным. Что приведет к краху программы.

Если интересно, я могу вечером выложить свой велосипед на эту тему.
« Последнее редактирование: 12-08-2008 12:13 от Finch » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
CTAPOBEP
Постоялец

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 12-08-2008 12:52 » 

ch="HGFEDCBA\n"; Тест не прошел Программа на выполнении упала.
printf("%s", ch); Тест не прошел Программа на выполнении упала.
ch[0]='a'; Тест не прошел. Программа на выполнении упала.

Странно, а у меня все это работает и выдает именно тот результат, какой должен быть. MSVS 6.0 + MFC. Велосипед выкладывай, я люблю велосипеды Улыбаюсь
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


WWW
« Ответ #4 : 12-08-2008 16:37 » 

Странно, а у меня все это работает и выдает именно тот результат, какой должен быть.
ты, случаем, не в ДОСе выполняешь ? Улыбаюсь
Записан

Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #5 : 12-08-2008 18:48 » 

Вот мой велосипед.
Код:
#include <assert.h>
#include <iostream>

template <class T>
class smart_ptr
{
   private:
      struct Tptr
      {
         int count;
         T *ptr;
         Tptr()
         {
            count=1;
            ptr=NULL;
         }
      };
     
      Tptr * ptr;
     
      void delete_ptr()
      {
         if (ptr != NULL)
         {
            ptr->count--;
            if (ptr->count == 0)
            {
               delete ptr->ptr;
               delete ptr;
            }
            ptr=NULL;
         }
      };
     
      void new_ptr(T *t)
      {
         delete_ptr();
         ptr=new Tptr;
         if (ptr != NULL) ptr->ptr=t;
      };
     
      void inc_ptr(Tptr *t)
      {
         delete_ptr();
         ptr=t;
         if (ptr != NULL) ptr->count++;
      }
     
   public:
      smart_ptr() {ptr=NULL;};
      smart_ptr(T *t) 
      {
         ptr=NULL;
         new_ptr(t);
      };
     
      smart_ptr(const smart_ptr<T> & cl)
      {
         ptr=NULL;
         inc_ptr(cl.ptr);
      };
     
      ~smart_ptr()
      {
         delete_ptr();
      };
     
      smart_ptr & operator = (T *t)
      {
         if (t != NULL)
         {
            new_ptr(t);
         }
         return *this;
      };
     
      smart_ptr & operator = (smart_ptr<T> & cl)
      {
          inc_ptr(cl.ptr);
          return *this;
      };
     
      T& operator *()
      {
         assert(ptr != NULL);
         assert(ptr->ptr != NULL);
         return *ptr->ptr;
         
      };
     
      T *operator ->()
      {
         assert(ptr != NULL);
         assert(ptr->ptr != NULL);
         return ptr->ptr;         
      };
     
      T *& get()
      {
         assert(ptr != NULL);
         assert(ptr->ptr != NULL);
         return ptr->ptr;         
      };
     
};

int main()
{
    smart_ptr<int> a(new int), b;
    *a = 123;
    std::cout << "*a.get() = " << *a << std::endl;
    b=a;
    if (a.get() == NULL)
       std::cout << "As result a.get() is NULL." << std::endl;
    std::cout << "*b.get() = " << *b.get() << std::endl;
    return 0;

}
[/quote]
Делал для своих нужд, поэтому особой функциональности прошу не ожидать :)
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
CTAPOBEP
Постоялец

ru
Offline Offline
Пол: Мужской

« Ответ #6 : 13-08-2008 04:30 » 

"ты, случаем, не в ДОСе выполняешь ?"

А что это такое ? Ага

Вот кусок кода, который у меня прекрасно работает:

Код:
BOOL CTestDlg::OnInitDialog()
{
CDialog::OnInitDialog();

// Set the icon for this dialog.  The framework does this automatically
//  when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon


New <char*> ch=new char [9];
strcpy(ch, "ABCDEFGH");
ch[8]=0x00;

AfxMessageBox(ch);

ch="HGFEDCBA\0";
AfxMessageBox(ch);

ch[0]='a';
ch[1]='b';
ch[2]='c';
ch[3]='d';
ch[4]='e';
ch[5]='f';
ch[6]='g';
ch[7]='h';
ch[8]='\0';

AfxMessageBox(ch);

if (!strcmp(ch, "abcdefgh")) AfxMessageBox("Равно !!!");
else AfxMessageBox("Не равно !!!");

return TRUE;  // return TRUE  unless you set the focus to a control
}

Finch, спасибо, есть куда расти Улыбаюсь

Так. Почему меня так мало пинают? Ну вот как в таких условиях код улучшать?
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #7 : 13-08-2008 10:51 » 

CTAPOBEP, Может ты не привел полностью код. Но конструкция ch[0]='a'; у тебя явно должна не работать. Так как, ты по крайней мере не переопредели []. У меня стоит компилятор g++ (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21). И на нем при компиляции выскакивают warning. При исполнении программа просто падает.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


WWW
« Ответ #8 : 13-08-2008 18:01 » 

CTAPOBEP, DOS я имею в виду )
Записан

CTAPOBEP
Постоялец

ru
Offline Offline
Пол: Мужской

« Ответ #9 : 14-08-2008 04:39 » 

Я привел тот код, который сам добавил, все остальное - дело рук Wizard'a. Вот проект целиком, желающие могут убедиться - http://slil.ru/26057820

По поводу непереопределенного оператора [] - есть оператор TYPE, от возвращает указатель, этого должно быть достаточно.


"CTAPOBEP, DOS я имею в виду )"

А я имею в виду, что даже слова такого не знаю Ага
Записан
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #10 : 14-08-2008 05:28 » 

поправил код ибо не айс:
Код:
template <class T> // че-то не люблю я стиль аля VS 6.0
class another_smart_ptr // суть класса
{
T * pointer_; // так оно надёжней, представь инстанцирование простым интом

public:
another_smart_ptr() : pointer_(NULL) {} // пишем на C++
another_smart_ptr(unsigned int num): pointer_(NULL) { pointer_ = new T [num]; }
another_smart_ptr(T * arg) { *this = arg; }
~another_smart_ptr(void) {if (pointer_) delete [] pointer_;}
T* operator= (T * arg)
{
if (pointer_) delete [] pointer_;
return pointer_ = arg;
}
operator T*() { return pointer_; } // не очень здорово, слишком не явно
operator const T*() const { return pointer_; } // иначе будут грабли в некоторых ситуациях
T* operator->() { return pointer_; }
};


int _tmain(int argc, _TCHAR* argv[])
{

another_smart_ptr<char> ch = new char[9];

// strcpy(ch, "ABCDEFGH\0"); это хрень " подразумевает завершающий ноль
strcpy(ch, "ABCDEFGH\0");
// ch[8]=0x00; и нафига мы его еще раз проставили

//ch = "HGFEDCBA"; а это самое интерестное
// подумаем, что тут происходит
// тут мы берём и копируем указатель на ВРЕМЕННЫЙ КОНСТАНТНЫЙ ЛОКАЛЬНЫЙ объект
// и нам это удаётся :), но компилятор сам решает: где, когда и как
// он хранит, создаёт и удаляет объект
// у нас есть одна гарантия он доступен пока не завершится operator=
strcpy(ch, "HGFEDCBA");

// ну то что его может в любом месте разорвать является следствием
// копирования указателя на константу
ch[0]='a';
ch[1]='b';
ch[2]='c';
ch[3]='d';
ch[4]='e';
ch[5]='f';
ch[6]='g';
ch[7]='h';
ch[8]='\0';

std::cout << strcmp(ch, "abcdefgh");

return 0;
}
Записан

Странно всё это....
CTAPOBEP
Постоялец

ru
Offline Offline
Пол: Мужской

« Ответ #11 : 14-08-2008 07:16 » 


"тут мы берём и копируем указатель на ВРЕМЕННЫЙ КОНСТАНТНЫЙ ЛОКАЛЬНЫЙ объект"

Согласен, так делать не следует. И вообще - не следует смешивать между собой указатели, объявленные обычным образом и объекты подобного класса.
Записан
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #12 : 14-08-2008 08:21 » 

CTAPOBEP, честно говоря этот класс кроме, как из праздного любопытства вообще не следовало писать.
есть же
std::string
std::vector<char>
std::auto_ptr
std::rope
boost::scoped_ptr
boost::scoped_array
boost::shared_ptr
boost::shared_array

для чего он нужен?
вот честно что он даёт?
для чего использовался?
Записан

Странно всё это....
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #13 : 14-08-2008 08:46 » 

совсем забыл.
Еще же есть boost pointer containers
работаешь как с вектором, а реально хранишь указатели красота

кстати вопрос, то был, какие проблемы
что, то я в коде уже отметил
в основном это не явное поведение класса
оператор равно делает не, то что ожидаем (лучше reset)
не метода передачи владения release
константные методы не реализованы
нет оператора приведения к bool
оператор неявного приведения к *, как не кажется не слишком удачное решение в плане прозрачности восприятия

в общем мне больше по душе интерфейс scoped_prt/shared_prt/auto_ptr
« Последнее редактирование: 14-08-2008 08:53 от LogRus » Записан

Странно всё это....
CTAPOBEP
Постоялец

ru
Offline Offline
Пол: Мужской

« Ответ #14 : 14-08-2008 12:10 » 


"кроме, как из праздного любопытства вообще не следовало писать"

Герберт Шилдт с тобой определенно не согласен Улыбаюсь  В своей книге "Искусство программирования на С++" он рассматривает целых два варианта подобного класса (и еще немножко касается теории этого вопроса).

За информацию - спасибо, беру на заметку.
Записан
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #15 : 15-08-2008 07:17 » 

Это не он со мной не согласен, это я с ним не согласен. Улыбаюсь

Не будем спорить о полезности изобретения велосипедов Улыбаюсь каждый проект уникален и требует индивидуального подхода.
Записан

Странно всё это....
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines