На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела Visual C++ / MFC / WTL (далее Раздела)
1) На Раздел распространяются все Правила Форума.
2) Перед тем, как создать новый топик, убедитесь, что Вы читали Правила создания тем в Разделе.
3) Вопросы, не связанные с программированием (настройки MS Visual Studio, книги, библиотеки и т.д.),
обсуждаются в разделе C/C++: Прочее
4) Вопросы разработки .NET (Windows Form, C++/CLI и т.п.) приложений на Visual C++/C# обсуждаются в разделе .NET.
5) Нарушение Правил может повлечь наказание со стороны модераторов.

Полезные ссылки:
user posted image FAQ Раздела user posted image Обновления для FAQ Раздела user posted image Поиск по Разделу user posted image MSDN Library Online
Модераторы: ElcnU
  
> Конструктор и delete this
    Есть у меня конструктор, правильно было бы, если я бы вызвал
    в нем или в методе, который он вызывает, delete this?
    Да и вообще можно ли вызывать в любом методе delete this?
    Соответствует ли это общим правилам?
      На сколько я представляю - ничего страшного не будет. Разумеется при delete this вызовется деструктор объекта, поэтому вызывать delete this в деструкторе лучше не надо - я не знаю что сделает компилятор в этом случае, в этом экзотичном случае разные компиляторы могут себя повести по разному - пострадает переносимость программы.

      И подумай - нужно ли вообще вызывать деструктор из метода класса, не лучше ли все что нужно поместить в деструктор класса и просто удалять объект по delete oPtr.
        delete this в методе класса - типичная практика. Но вот вызов такого метода из конструктора - это нонсенс. Представь себе, что объект создается на стеке и для него вызывается такой конструктор.
          Да, а если для объекта на стеке вызовется такой (c delete this) метод, то все будет ок?
            Нет не будет. Все посыпется. Но! Типичная реализация метода Release для COM-компонентов - if (m_RefCounter == 0) delete this;. Это также справедливо для ситуаций, когда несколько подсистем взаимодействуют между собой посредством интерфейсов. Согласись, в этом случае не будет объектов, распределенных на стеке.
            А delete this в конструкторе черевато тем, что new вернет указатель на заведомо освобожденный блок памяти.
              Цитата Flex Ferrum, 09.06.03, 13:22:11
              delete this в методе класса - типичная практика.

              А когда так делают???? Ни разу не видел... :-/
                Цитата byte, 09.06.03, 20:56:51

                А когда так делают???? Ни разу не видел... :-/

                Flex_Ferrum же написал - при управлении временем жизни объекта на основании подсчета ссылок
                  Цитата byte, 09.06.03, 20:56:51

                  А когда так делают???? Ни разу не видел... :-/

                  Немодальный диалог никогда в эмэфцэ не делал?
                    Ну, знаешь ли, немодальный диалог можно и без delete this сделать, чем в общем то я и занимаюсь..
                      Цитата e-yes, 10.06.03, 12:44:14

                      Немодальный диалог никогда в эмэфцэ не делал?

                      Пока нет :D. А что, там все с ними так запущено? \%)
                        Да нет... просто см. соответствующий TechNote. Это в порядке вещей ;)
                          >>delete this в методе класса - типичная практика. Но вот вызов такого метода из >>конструктора - это нонсенс. Представь себе, что объект создается на стеке и для >>него вызывается такой конструктор.
                          Поподрбней, я непонял почему так нельзя...
                            Блин! Как квотинг делать?
                              Цитата Туту, 11.06.03, 09:45:19
                              >>delete this в методе класса - типичная практика. Но вот вызов такого метода из >>конструктора - это нонсенс. Представь себе, что объект создается на стеке и для >>него вызывается такой конструктор.
                              Поподрбней, я непонял почему так нельзя...


                              потому что обычные (неперегруженные) new и  delete работают с кучей, а не со стеком, для стека память не освобождается, а просто перещелкивается стекпоинтер.

                              А квотировать - это по русски означает "цитировать" :)
                                А потому, что при выделении объекта на стеке память ему распределяется не из пула (читай - не вызывается оператор new), и в этом случае вызывать для этого объекта delete - смерти подобно.
                                  Цитата Adil, 11.06.03, 12:50:28

                                  А квотировать - это по русски означает "цитировать" :)
                                  Туту, имеется ввиду что над каждым сообщением справа есть кнопка Цитировать
                                    Цитата Flex Ferrum, 11.06.03, 15:53:16
                                    А потому, что при выделении объекта на стеке память ему распределяется не из пула (читай - не вызывается оператор new), и в этом случае вызывать для этого объекта delete - смерти подобно.


                                    А когда память выделяется на стеке? (и почему) и зачем это надо вообще?
                                    Как это вообще выглядит?
                                    Ты не мог бы привести примера, что-бы было "смерти подобно",
                                    то есть в конструкторе или в методе вызвать delete this, и все "сломалось" бы.
                                    Видимо сначала надо определится что-такое не на стеке.
                                    И вообще при создании объекта я же пишу что-то в духе;
                                    CWindow1 *CWindow1a=new CWindow(....);
                                    Оператор new присутствует.
                                    Если я вызываю delete в методе или конструкторе, delete удалает выделенную
                                    память (вообще название пул ты сам придумал или это общепринято)
                                    и вызывает деструктор, так вот в том методе из которого было вызвано delete
                                    будет дальше работать или нет? (видимо должно быть "смерти подобно";)

                                      Память на стеке выделяется обычно чаще, чем в "обычной" памяти - почти всегда для локальных переменных (почти - т.к., если хватает регистров и стоит соответствующая опция компиляции, они (лок. перем.) могут "размещаться" в регистрах процессора).
                                      Пример:
                                      ExpandedWrap disabled
                                        <br>void main()<br>{//начало какого-либо блока, необязательно main<br>  double d,w;<br>  int i,k;<br>}<br>

                                      - все эти переменные будут размещенны на стеке. Что это значит: вот я дизассемблировал и посмотри на асм-код:
                                      ExpandedWrap disabled
                                        <br>@_main      proc      near<br>      push      ebp<br>      mov       ebp,esp<br>      add       esp,-24 ;вот здесь и занимается место на стеке под локальные:<br>                                    ; просто смещается указатель на начало (конец? :) ) стека <br><br>      mov       esp,ebp ;а здесь стек освобождается, можно было и "add esp, 24"<br>      pop       ebp<br>      ret <br>@_main      endp<br>


                                      А если ты напишешь
                                      ExpandedWrap disabled
                                        <br>MyClass<br>{<br>public:<br>  MyClass(){}<br>  ~MyClass{}<br>  void SelfKill(){delete this;}<br>};<br>void main()<br>{<br>  MyClass mc;<br>  mc.SelfKill();<br>  printf("\nEnd main");<br>}<br>

                                      то "delete this;" в "SelfKill()" попытается освободить память из стека, а не из кучи (пула).
                                      Что при этом произойдет? - да какое угодно непотребство. В приведенном примере программа просто висла на "delete this;" (до "printf("\nEnd main");" дело не доходило.
                                      Это под XP - под 9x или под DOS все может быть гораздо хуже.

                                      Если хочется использовать "delete this;", то надо быть уверенным, что все объекты класса создаются в куче (как, например, TObject и все его наследники в VCL Borland'a).

                                      ЗЫ: Вообще, есть простое правило: если есть new, то должен быть и delete, и наоборот. И лучше его придерживаться.
                                        Чтобы быть уверенным, что объекты создаются в куче, достаточно сделать конструкторы закрытыми и перегрузить new
                                          Конструктор если закрыт, то как его вызвать?
                                            Цитата Туту, 13.06.03, 11:07:14
                                            Конструктор если закрыт, то как его вызвать?


                                            написано же "перегрузить оператор new"
                                              Можно лучше пример? или не хуже будет, просто комментарий..
                                                Да... Правильно. Как-то не удалось вызвать перегруженый new при наличии закрытого конструктора. Но есть способ получше.
                                                Можно сделать закрытым только деструктор.
                                                ExpandedWrap disabled
                                                  <br>class Foo{<br>...<br>public:<br>   Foo(){<br>    // можно и delete this; Но надо как-то увидеть из-вне, что объект уничтожен.<br>   // Это можно сделать перегрузкой operator new, котоый вернет NULL в данном случае<br>  }<br>//Другие конструкторы. Методы<br><br>//Самоуничтожение(или самоубийство :)).<br>   void SelfDestruct(){<br>    ...<br>      delete this; // и вызов ~Foo();<br>   }<br>protected:<br>    ~Foo(){<br>       ...<br>   }<br>...<br>};<br><br>void SomeFunc(){<br>   Foo a; //Не пройдет -  'Foo::~Foo' : cannot access protected member declared in class 'Foo'<br>    <br>    Foo *b = new Foo; // Нормально<br><br>    delete b; // не пойдет. Одна из жертв данного метода.<br><br><br>//деструктор. Удаление памяти  - <br>     b->SelfDestruct();<br>// Они вынуждены быть самоубийцами... Это жестоко.<br> <br>}<br><br>

                                                Другие жертвы метода
                                                - нельзя сделать массив этих объектов(точнее их уничтожить с помощью delete []) .
                                                - передача парометра в функцию только по ссылке. И вообще работа с ними возможна только с помощью указателей/ссылок.

                                                Но можно быть уверенным, что такой объект не окажется в стеке. А delete this является необходимым.


                                                Сообщение отредактировано: rcz -
                                                1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                                                0 пользователей:


                                                Рейтинг@Mail.ru
                                                [ Script execution time: 0,0724 ]   [ 15 queries used ]   [ Generated: 18.07.25, 01:09 GMT ]