
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[216.73.216.207] |
![]() |
|
Сообщ.
#1
,
|
|
|
Есть у меня конструктор, правильно было бы, если я бы вызвал
в нем или в методе, который он вызывает, delete this? Да и вообще можно ли вызывать в любом методе delete this? Соответствует ли это общим правилам? |
Сообщ.
#2
,
|
|
|
На сколько я представляю - ничего страшного не будет. Разумеется при delete this вызовется деструктор объекта, поэтому вызывать delete this в деструкторе лучше не надо - я не знаю что сделает компилятор в этом случае, в этом экзотичном случае разные компиляторы могут себя повести по разному - пострадает переносимость программы.
И подумай - нужно ли вообще вызывать деструктор из метода класса, не лучше ли все что нужно поместить в деструктор класса и просто удалять объект по delete oPtr. |
Сообщ.
#3
,
|
|
|
delete this в методе класса - типичная практика. Но вот вызов такого метода из конструктора - это нонсенс. Представь себе, что объект создается на стеке и для него вызывается такой конструктор.
|
Сообщ.
#4
,
|
|
|
Да, а если для объекта на стеке вызовется такой (c delete this) метод, то все будет ок?
|
Сообщ.
#5
,
|
|
|
Нет не будет. Все посыпется. Но! Типичная реализация метода Release для COM-компонентов - if (m_RefCounter == 0) delete this;. Это также справедливо для ситуаций, когда несколько подсистем взаимодействуют между собой посредством интерфейсов. Согласись, в этом случае не будет объектов, распределенных на стеке.
А delete this в конструкторе черевато тем, что new вернет указатель на заведомо освобожденный блок памяти. |
Сообщ.
#6
,
|
|
|
Цитата Flex Ferrum, 09.06.03, 13:22:11 delete this в методе класса - типичная практика. А когда так делают???? Ни разу не видел... :-/ |
Сообщ.
#7
,
|
|
|
Цитата byte, 09.06.03, 20:56:51 А когда так делают???? Ни разу не видел... :-/ Flex_Ferrum же написал - при управлении временем жизни объекта на основании подсчета ссылок |
Сообщ.
#8
,
|
|
|
Цитата byte, 09.06.03, 20:56:51 А когда так делают???? Ни разу не видел... :-/ Немодальный диалог никогда в эмэфцэ не делал? |
Сообщ.
#9
,
|
|
|
Ну, знаешь ли, немодальный диалог можно и без delete this сделать, чем в общем то я и занимаюсь..
|
Сообщ.
#10
,
|
|
|
Цитата e-yes, 10.06.03, 12:44:14 Немодальный диалог никогда в эмэфцэ не делал? Пока нет ![]() |
Сообщ.
#11
,
|
|
|
Да нет... просто см. соответствующий TechNote. Это в порядке вещей
![]() |
Сообщ.
#12
,
|
|
|
>>delete this в методе класса - типичная практика. Но вот вызов такого метода из >>конструктора - это нонсенс. Представь себе, что объект создается на стеке и для >>него вызывается такой конструктор.
Поподрбней, я непонял почему так нельзя... |
Сообщ.
#13
,
|
|
|
Блин! Как квотинг делать?
|
Сообщ.
#14
,
|
|
|
Цитата Туту, 11.06.03, 09:45:19 >>delete this в методе класса - типичная практика. Но вот вызов такого метода из >>конструктора - это нонсенс. Представь себе, что объект создается на стеке и для >>него вызывается такой конструктор. Поподрбней, я непонял почему так нельзя... потому что обычные (неперегруженные) new и delete работают с кучей, а не со стеком, для стека память не освобождается, а просто перещелкивается стекпоинтер. А квотировать - это по русски означает "цитировать" ![]() |
Сообщ.
#15
,
|
|
|
А потому, что при выделении объекта на стеке память ему распределяется не из пула (читай - не вызывается оператор new), и в этом случае вызывать для этого объекта delete - смерти подобно.
|
Сообщ.
#16
,
|
|
|
Цитата Adil, 11.06.03, 12:50:28 Туту, имеется ввиду что над каждым сообщением справа есть кнопка ЦитироватьА квотировать - это по русски означает "цитировать" ![]() |
Сообщ.
#17
,
|
|
|
Цитата Flex Ferrum, 11.06.03, 15:53:16 А потому, что при выделении объекта на стеке память ему распределяется не из пула (читай - не вызывается оператор new), и в этом случае вызывать для этого объекта delete - смерти подобно. А когда память выделяется на стеке? (и почему) и зачем это надо вообще? Как это вообще выглядит? Ты не мог бы привести примера, что-бы было "смерти подобно", то есть в конструкторе или в методе вызвать delete this, и все "сломалось" бы. Видимо сначала надо определится что-такое не на стеке. И вообще при создании объекта я же пишу что-то в духе; CWindow1 *CWindow1a=new CWindow(....); Оператор new присутствует. Если я вызываю delete в методе или конструкторе, delete удалает выделенную память (вообще название пул ты сам придумал или это общепринято) и вызывает деструктор, так вот в том методе из которого было вызвано delete будет дальше работать или нет? (видимо должно быть "смерти подобно";) |
Сообщ.
#18
,
|
|
|
Память на стеке выделяется обычно чаще, чем в "обычной" памяти - почти всегда для локальных переменных (почти - т.к., если хватает регистров и стоит соответствующая опция компиляции, они (лок. перем.) могут "размещаться" в регистрах процессора).
Пример: ![]() ![]() <br>void main()<br>{//начало какого-либо блока, необязательно main<br> double d,w;<br> int i,k;<br>}<br> - все эти переменные будут размещенны на стеке. Что это значит: вот я дизассемблировал и посмотри на асм-код: ![]() ![]() <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> А если ты напишешь ![]() ![]() <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, и наоборот. И лучше его придерживаться. |
Сообщ.
#19
,
|
|
|
Чтобы быть уверенным, что объекты создаются в куче, достаточно сделать конструкторы закрытыми и перегрузить new
|
Сообщ.
#20
,
|
|
|
Конструктор если закрыт, то как его вызвать?
|
Сообщ.
#21
,
|
|
|
Цитата Туту, 13.06.03, 11:07:14 Конструктор если закрыт, то как его вызвать? написано же "перегрузить оператор new" |
Сообщ.
#22
,
|
|
|
Можно лучше пример? или не хуже будет, просто комментарий..
|
Сообщ.
#23
,
|
|
|
Да... Правильно. Как-то не удалось вызвать перегруженый new при наличии закрытого конструктора. Но есть способ получше.
Можно сделать закрытым только деструктор. ![]() ![]() <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 является необходимым. |