-
1. Data: 2009-07-28 16:00:41
Temat: [c++]Prosta klasa, czemu nie wywołuje destruktorów?
Od: "P.K.D" <g...@g...com>
Tutaj ta klasa: http://paste.dprogramming.com/dpibqklz
Chodzi o to, że gdy wywołuję server::clearList() to obiekty nie są
niszczone, chyba dlatego, że lista zawiera wskaźniki. Jak to zrobić i
czy da się zrobić tak, że destruktory będą wywoływane automatycznie?
Jak się komuś nie chce linka czytać:
W kodzie jest:
server* srv = new server(name, address, port);
A w konstruktorze
servers.push_back(this);
gdzie servers to statyczna w klasie server:
static std::list<server *> servers;
no ale gdy wywołuję metodę clear() z std::list nie są wywoływane
destruktory elementów listy gdzie jest intrukcja:
delete this;
przez co nie jest zwalniana pamięć po zakończeniu programu. Chciałbym
jednak by była i nie wiem jak to zrobić. Z góry dziękuję :)
--
Life is great, but still... we're all trapped. Each of us is stuck being
who we are. Sometimes we fight to change ourselves, but ultimately this
has little effect. We can change what we do, but we cannot change who we
are.
-
2. Data: 2009-07-28 17:52:03
Temat: Re: [c++]Prosta klasa, czemu nie wywołuje destruktorów?
Od: grg12 <g...@c...at>
P.K.D pisze:
> Tutaj ta klasa: http://paste.dprogramming.com/dpibqklz
>
> Chodzi o to, że gdy wywołuję server::clearList() to obiekty nie są
> niszczone, chyba dlatego, że lista zawiera wskaźniki. Jak to zrobić i
> czy da się zrobić tak, że destruktory będą wywoływane automatycznie?
Dokładnie dlatego - masz listę wskaźników na obiekty a nie obiektów -
wywoływany jest więc "destruktor" wskaźnika :)
Możesz np. w metodzie clearList przelecieć po wszystkich elementach
zmiennej "servers" i wywołać ich destruktory np. tak:
for(std::list<server *>::iterator ii=servers.begin();ii!=servers.end();
ii++)
{
delete (*ii);
}
servers.clear();
Tyle że ciało tej funkcji prawdopodobnie trzeba będzie zdefiniować poza
klasą - w tym miejscu gdzie jest teraz destruktor jeszcze nie jest
zadeklarowany.
I jeszcze jedno - "delete this" w destruktorze to kiepski pomysł (no
chyba że się coś w specyfikacji języka zmieniło?). Normalnie wywołanie
destruktora jest konsekwencja wywołania delete - destruktor to "ostatnia
szansa na posprzątanie zanim system zwolni pamięć" (np. zwolnić pliki,
usunąć podobiekty utworzone przez new). W twoim przypadku destruktor
może być pusty - jeśli koniecznie chcesz coś tam mieć - wstaw "std::cout
<< "obiekt typu server o nazwie"<<name<<" właśnie popełnia
seppuku"<<std::endl;
Pozdrawiam
GRG
-
3. Data: 2009-07-28 17:54:11
Temat: Re: [c++]Prosta klasa, czemu nie wywołuje destruktorów?
Od: Tomasz Bywalec <t...@p...dont.spam.me.o2.pl>
P.K.D pisze:
> Tutaj ta klasa: http://paste.dprogramming.com/dpibqklz
>
> Chodzi o to, że gdy wywołuję server::clearList() to obiekty nie są
> niszczone, chyba dlatego, że lista zawiera wskaźniki. Jak to zrobić i
> czy da się zrobić tak, że destruktory będą wywoływane automatycznie?
>
> Jak się komuś nie chce linka czytać:
>
> W kodzie jest:
> server* srv = new server(name, address, port);
>
> A w konstruktorze
> servers.push_back(this);
>
> gdzie servers to statyczna w klasie server:
> static std::list<server *> servers;
>
> no ale gdy wywołuję metodę clear() z std::list nie są wywoływane
> destruktory elementów listy gdzie jest intrukcja:
> delete this;
Usuwanie elementów z listy (lub dowolnej innej stl'owej kolekcji)
zawsze powoduje usunięcie tych elementów - tyle że w Twoim
przypadku elementami listy są wskaźniki. W takim razie niszczone
są właśnie wskaźniki ale nie obiekty na które wskazują.
Do głowy przychodzą mi dwa sposoby:
1. Napisać osobną klasę reprezentującą listę serwerów -
przechowywałaby ona listę std::list<server*> jako pole
prywatne, natomiast dostęp do listy odbywałby się
przy pomocy metod 'add()' (dodaje wskaźnik do listy),
'remove()' (usuwa wskaźnik i jednocześnie niszczy wskazywany
przez niego obiekt) oraz 'clear()' (czyli 'remove()' dla
wszystkich elementów listy) plus jakieś metody umożliwiające
przeglądanie listy. I zastąpić typ pola 'servers' tą klasą.
2. Zamiast std::list użyć boost::ptr_list, która po usunięciu
wskaźnika z listy niszczy również wskazywany obiekt:
http://www.boost.org/doc/libs/1_39_0/libs/ptr_contai
ner/doc/ptr_container.html
Pozdrawiam,
Tomek Bywalec
-
4. Data: 2009-07-28 20:11:26
Temat: Re: [c++]Prosta klasa, czemu nie wywołuje destruktorów?
Od: "P.K.D" <g...@g...com>
W dniu 2009-07-28 19:52, grg12 pisze:
> P.K.D pisze:
>> Tutaj ta klasa: http://paste.dprogramming.com/dpibqklz
>>
>> Chodzi o to, że gdy wywołuję server::clearList() to obiekty nie są
>> niszczone, chyba dlatego, że lista zawiera wskaźniki. Jak to zrobić i
>> czy da się zrobić tak, że destruktory będą wywoływane automatycznie?
>
> Dokładnie dlatego - masz listę wskaźników na obiekty a nie obiektów -
> wywoływany jest więc "destruktor" wskaźnika :)
> Możesz np. w metodzie clearList przelecieć po wszystkich elementach
> zmiennej "servers" i wywołać ich destruktory np. tak:
>
> for(std::list<server *>::iterator ii=servers.begin();ii!=servers.end();
> ii++)
> {
> delete (*ii);
> }
>
> servers.clear();
>
> Tyle że ciało tej funkcji prawdopodobnie trzeba będzie zdefiniować poza
> klasą - w tym miejscu gdzie jest teraz destruktor jeszcze nie jest
> zadeklarowany.
>
> I jeszcze jedno - "delete this" w destruktorze to kiepski pomysł (no
> chyba że się coś w specyfikacji języka zmieniło?). Normalnie wywołanie
> destruktora jest konsekwencja wywołania delete - destruktor to "ostatnia
> szansa na posprzątanie zanim system zwolni pamięć" (np. zwolnić pliki,
> usunąć podobiekty utworzone przez new). W twoim przypadku destruktor
> może być pusty - jeśli koniecznie chcesz coś tam mieć - wstaw "std::cout
> << "obiekt typu server o nazwie"<<name<<" właśnie popełnia
> seppuku"<<std::endl;
> Pozdrawiam
> GRG
Ok, przemyślałem i faktycznie delete this to idiotyzm. Dzięki, że o tym
wspomniałeś:) W końcu nie miałem wyjścia i zrobiłem swoją funkcję
clear(), ale myślałem, że może jest jakiś inny sposób przewidziany do
pracy z takimi listami. No ale niezadowolony jestem, bo chciałbym żeby
ta lista się sama czyściła. Będę musiał chyba napisać osobną klasę jak
to Tomasz opisał. Dzięki za odpowiedzi:)
--
Life is great, but still... we're all trapped. Each of us is stuck being
who we are. Sometimes we fight to change ourselves, but ultimately this
has little effect. We can change what we do, but we cannot change who we
are.
-
5. Data: 2009-07-29 11:37:07
Temat: Re: [c++]Prosta klasa, czemu nie wywołuje destruktorów?
Od: "Mateusz Loskot" <m...@l...net>
"P.K.D" <g...@g...com> wrote in message
news:h4n80i$97a$1@mx1.internetia.pl...
> przez co nie jest zwalniana pamięć po zakończeniu programu. Chciałbym
> jednak by była i nie wiem jak to zrobić. Z góry dziękuję :)
Po za kończeniu programu (procesu), pamięć zostanie zwolniona,
o to się nie martw.
Pozdrawiam
--
Mateusz Loskot, http://mateusz.loskot.net
pl.comp.lang.c FAQ: http://pl.cpp.wikia.com/wiki/FAQ
C++ FAQ: http://parashift.com/c++-faq-lite
-
6. Data: 2009-07-29 11:37:33
Temat: Re: [c++]Prosta klasa, czemu nie wywołuje destruktorów?
Od: Mariusz Kruk <M...@e...eu.org>
epsilon$ while read LINE; do echo \>"$LINE"; done < "Mateusz Loskot"
>> przez co nie jest zwalniana pamięć po zakończeniu programu. Chciałbym
>> jednak by była i nie wiem jak to zrobić. Z góry dziękuję :)
>Po za kończeniu programu (procesu), pamięć zostanie zwolniona,
>o to się nie martw.
"zakończeniu".
Poza tym milcząco zakładasz, że środowisko samo posprząta. A nie zawsze
tak jest. Sprzątanie po sobie jest dobrą praktyką.
--
\.\.\.\.\.\.\.\.\.\.\.\.\.\ (If you're confused by all this, try typing
.\....@e...eu.org.\.\. `I}' now.)(TeX)
\.http://epsilon.eu.org/\.\
.\.\.\.\.\.\.\.\.\.\.\.\.\.
-
7. Data: 2009-07-29 11:53:33
Temat: Re: [c++]Prosta klasa, czemu nie wywołuje destruktorów?
Od: Tomasz Kaczanowski <kaczus@dowyciecia_poczta.onet.pl>
P.K.D pisze:
> W dniu 2009-07-28 19:52, grg12 pisze:
>> P.K.D pisze:
>>> Tutaj ta klasa: http://paste.dprogramming.com/dpibqklz
>>>
>>> Chodzi o to, że gdy wywołuję server::clearList() to obiekty nie są
>>> niszczone, chyba dlatego, że lista zawiera wskaźniki. Jak to zrobić i
>>> czy da się zrobić tak, że destruktory będą wywoływane automatycznie?
>>
>> Dokładnie dlatego - masz listę wskaźników na obiekty a nie obiektów -
>> wywoływany jest więc "destruktor" wskaźnika :)
>> Możesz np. w metodzie clearList przelecieć po wszystkich elementach
>> zmiennej "servers" i wywołać ich destruktory np. tak:
>>
>> for(std::list<server *>::iterator ii=servers.begin();ii!=servers.end();
>> ii++)
>> {
>> delete (*ii);
>> }
>>
>> servers.clear();
>>
>> Tyle że ciało tej funkcji prawdopodobnie trzeba będzie zdefiniować poza
>> klasą - w tym miejscu gdzie jest teraz destruktor jeszcze nie jest
>> zadeklarowany.
>>
>> I jeszcze jedno - "delete this" w destruktorze to kiepski pomysł (no
>> chyba że się coś w specyfikacji języka zmieniło?). Normalnie wywołanie
>> destruktora jest konsekwencja wywołania delete - destruktor to "ostatnia
>> szansa na posprzątanie zanim system zwolni pamięć" (np. zwolnić pliki,
>> usunąć podobiekty utworzone przez new). W twoim przypadku destruktor
>> może być pusty - jeśli koniecznie chcesz coś tam mieć - wstaw "std::cout
>> << "obiekt typu server o nazwie"<<name<<" właśnie popełnia
>> seppuku"<<std::endl;
>> Pozdrawiam
>> GRG
>
> Ok, przemyślałem i faktycznie delete this to idiotyzm. Dzięki, że o tym
> wspomniałeś:) W końcu nie miałem wyjścia i zrobiłem swoją funkcję
> clear(), ale myślałem, że może jest jakiś inny sposób przewidziany do
> pracy z takimi listami. No ale niezadowolony jestem, bo chciałbym żeby
> ta lista się sama czyściła. Będę musiał chyba napisać osobną klasę jak
> to Tomasz opisał. Dzięki za odpowiedzi:)
>
Nie - jest bardzo dobrze - to co jest allokowane przez obiekt, czyścić
powinien obiekt, jeśli ty allokujesz, to powinieneś ty zwalniać. Jeśli
byłoby inaczej, nigdy byś nie wiedział, co zwalniać, a co nie i wtedy
byłby bałagan.
--
Kaczus
http://kaczus.republika.pl
-
8. Data: 2009-07-29 12:29:12
Temat: Re: [c++]Prosta klasa, czemu nie wywołuje destruktorów?
Od: Tomasz Bywalec <t...@p...dont.spam.me.o2.pl>
Tomasz Kaczanowski pisze:
[...]
>
> Nie - jest bardzo dobrze - to co jest allokowane przez obiekt, czyścić
> powinien obiekt, jeśli ty allokujesz, to powinieneś ty zwalniać. Jeśli
> byłoby inaczej, nigdy byś nie wiedział, co zwalniać, a co nie i wtedy
> byłby bałagan.
>
Wydaje mi się, że przeoczyłeś fakt, że w oryginalnym kodzie P.K.D.
"delete this;" jest wywoływane w destruktorze. Pod pewnymi warunkami
jest to dopuszczalne w innych metodach obiektu, ale użycie tego w
destruktorze może tylko narobić problemów. Jeżeli obiekt został
utworzony na stosie to instrukcja ta bodajże doprowadzi do UB, jeśli
natomiast obiekt znajduje się na stercie to "delete ten_obiekt;" zostało
już wywołane i na pewno nie ma potrzeby wywoływania go ponownie na tym
samym obiekcie.
Pozdrawiam,
Tomek Bywalec
-
9. Data: 2009-07-29 12:53:23
Temat: Re: [c++]Prosta klasa, czemu nie wywołuje destruktorów?
Od: "Mateusz Loskot" <m...@l...net>
"Mariusz Kruk" <M...@e...eu.org> wrote in message
news:slrnh70d3t.6ka.Mariusz.Kruk@epsilon.rdc.pl...
> epsilon$ while read LINE; do echo \>"$LINE"; done < "Mateusz Loskot"
>>> przez co nie jest zwalniana pamięć po zakończeniu programu. Chciałbym
>>> jednak by była i nie wiem jak to zrobić. Z góry dziękuję :)
>>Po za kończeniu programu (procesu), pamięć zostanie zwolniona,
>>o to się nie martw.
>
> "zakończeniu".
> Poza tym milcząco zakładasz, że środowisko samo posprząta. A nie zawsze
> tak jest. Sprzątanie po sobie jest dobrą praktyką.
Oczywiście, że jest dobrą praktyką, ale 1) chodziło mi o wskazanie
pewnej niejednoznaczności w oryginalnym pytaniu 2) o dziwo, bywają
sytuacje gdy nie ma potrzeby aby zawacać sobie tym głowę.
Pozdrawiam
--
Mateusz Loskot, http://mateusz.loskot.net
pl.comp.lang.c FAQ: http://pl.cpp.wikia.com/wiki/FAQ
C++ FAQ: http://parashift.com/c++-faq-lite
-
10. Data: 2009-07-29 12:54:33
Temat: Re: [c++]Prosta klasa, czemu nie wywołuje destruktorów?
Od: "Mateusz Loskot" <m...@l...net>
"Mateusz Loskot" <m...@l...net> wrote in message
news:h4pgko$gfi$1@inews.gazeta.pl...
> 2) o dziwo, bywają sytuacje gdy nie ma potrzeby aby zawacać sobie tym
> głowę.
Na przykład, interesuje mnie prosty test:
#include <new>
int main(void)
{
std::size_t c = 0;
while (new(std::nothrow) char)
++c;
return c;
}
$ ./test
$ echo $?
Pozdrawiam
--
Mateusz Loskot, http://mateusz.loskot.net
pl.comp.lang.c FAQ: http://pl.cpp.wikia.com/wiki/FAQ
C++ FAQ: http://parashift.com/c++-faq-lite