Newsgroup: it.comp.lang.c++
Titolo: chiarimenti sui distruttori..

salve,
volevo chiedervi un chiarimento su come vengono chiamati i distruttori..
se io ho una classe, e in questa ad esempio creo un array(con new),  e
imposto anche un distruttore per la classe (che con delete mi cancella
l'array), quando e come viene chiamato?
il mio problema è che ho una classe che ha al suo interno una matrice di
unsigner char abbastanza grande (circa 200x200), ma in realtà nella main
devo creare un array di questa classe di circa 128 elementi. ora, con le ram
che ci sono in giro oggi non è un problema, ma cmq di certo non mi ispira il
fatto di sfruttarla male!
le operazioni che svolgo sono di confronto tra elementi delle prima matrice
e gli elementi delle restanti 127 , ma una volta finito il confronto (una
volta per matrice) di quella classe non me ne faccio + nulla.
ora mi chiedo, a chi spetta capire che tenere in memoria questa classe è
inutile? ci pensa il compilatore o devo indicarlo io chiamando in qualche
modo il distruttore??
grazie mille !!
jojo


Gabriele

 volevo chiedervi un chiarimento su come vengono chiamati i distruttori..
Il distruttore di un oggetto, viene invocato(secondo le regole del c++)
quando tale  oggetto non deve essere piu' referenziato, ossia all' uscita
del suo scope, per oggetti automatici(allocati nello stack), o quando viene
esplicitamente invocata la delete di un oggetto allocato nell' heap.
Ovviamente e' possibile invocare esplicitamente il metodo distruttore, ma e'
fortemente sconsigliato, se non per rari casi eccezionali.
--
Ivan Molella
ICQ: 162760950

 viene invocato il distruttore della tua classe;
è proprio questo il caso;
io creavo gli oggetti all'inizio della main function (stile C pr intenderci)
poi però gli usavo solo all'interno del ciclo for, e all'uscita da questo
ciclo potevano pure essere cancellati.
perciò conviene dichiararli direttamente all'interno di questo ciclo per
"snellire" il programma !?
grazie mille !!!
jojo

 jojo
Prego, anzi scusa per il post di prima che era orribile.
Gabriele

 mi ispira il fatto di sfruttarla male!
la risposta te l'hanno gia` data, pero` mi premeva sottolinearti che IMHO 
questo e` l'approccio sbagliato alla programmazione; uno dei piu` grandi 
informatici di tutti i tempi, Donald Knuth, disse questa frase:
"L'ottimizzazione prematura e` la radice di tutti i mali"
Se non hai un motivo piu` che valido non cercare di ottimizzare memoria o 
tempo di esecuzione: fallo solo quando sei *sicuro* che il tuo programma 
spreca troppe risorse; di solito tale sicurezza di acquisice solo *dopo* 
aver scritto il programma: quando ti accorgi che spreca troppa memoria o 
e` troppo lento ottimizzi dove e` necessario, ma non farlo *mai* prima, 
altrimenti rischi solamente di triplicare il tempo di stesura del codice 
e decuplicare i bug del codice.
Tra l'altro nel caso specifico difficilmente l'ottimizzazione da te 
pensata sara` sensibile; dici di allocare la memoria con "new" 
all'interno della tua classe, ma quando c'e` di mezzo la memoria 
dinamica tra il tuo programma e la RAM ci sono tot livelli di astrazione 
che ti impediscono di avere il pieno controllo su quello che e` allocato 
e quello che non lo e`: ad esempio puo` succedere che il sistema di 
run-time del C++ decida di *non* restituire la memoria al sistema 
operativo anche dopo una delete: quindi se guardi nella tabella dei 
processi vedi che il tuo programma utilizza sempre la stessa quantita` 
di memoria sia prima che dopo la delete-expression; tale memoria 
potrebbe essere liberata solo alla conclusione del programma stesso. 
Ovviamenente questo comportamento varia da sistema a sistema e da 
compilatore a compilatore, ma se hai problemi del genere e` da tenere 
presente.
Ovviamente se lo scopo della tua domanda era di imparare meglio i 
meccanismi di gestione della memoria del C++ era perfettamente legittima 
ed hai fatto benissimo a farla; ma se lo scopo era "risparmiare qualche 
byte di memoria" forse non era poi cosi` importante...
ciao Anto
-- 
"Computer science is not about computers any more than astronomy
is about telescopes." -- EW Dijkstra

 genere e` da tenere presente.
???
ma non si decanta il C++ proprio per il controllo sulla memoria
a basso livello?
Me lo spieghi meglio?
Perchè la situazione è differente nel caso non si usi la new?
--
Gerolamo

 Perchè la situazione è differente nel caso non si usi la new?
Perche' se ti gestisci le cose da te puoi fare cose diverse da quelle 
che fa new. Cio' non elimina pero' i vincoli posti dal sistema sottostante.
Ciao,
Nicola

ma quindi in definitiva è meglio fregarmene dell'allocazione della memoria
fino a quando non avrò problemi?
ma cmq se li avrò non sarà troppo tardi? Anche perchè sto lavorando in
ambiente Win, (anche se stò programmando prettamente in ansi c++) e questo
sistema, quando c'è qualcosa che non va non fa altro che andare in crash,
perciò prima di capire cosa è l'errore devo rispulciarmi TUTTO il codice...
ti spiego, stò lavorando alla tesi, e parte predominante della tesi è
ottenere un codec in c++.
per ora stò lavorando con immagini (array di unsigned char appunto)
piccole(176*144), e in numero di 128.
ma oltretutto ho scoperto proprio in questi giorni che per avere dati
statistici affidabili ho necessità di utilizzare un insieme molto + grande
di quello inizialmente stanziato (almeno 1000 immagini).
ad esempio : 176*144*1000 =25344000 byte di dati da confrontare.. e forse
non basteranno.
in questo caso  ?
un'altra domanda :
perchè è meglio usare new e delete anzichè malloc e free?
grazie a tutti !!!!

 a basso livello?
scusami, ho preso un granchio fenomenale...
nel mio post ho scritto "memoria dinamica" ma pensavo piu` che altro agli 
allocatori standard (che non c'entravano nulla in questo contesto).
Correggo: e` probabile che delete rilasci subito la memoria al sistema 
operativo, anche se nessuno ce lo assicura (soprattutto se usiamo classi 
con allocatori personalizzati).


 con allocatori personalizzati).
Io invece resto dell'idea che il comportamento che hai descritto nel 
post precedente sia quello piu' probabile...
Ciao,
Nicola

 perchè è meglio usare new e delete anzichè malloc e free?
Perchè new e delete invocano costruttori e distruttori,
mentre malloc e free no.
-- 
Gerolamo

 post precedente sia quello piu' probabile...
anche a me sembrerebbe una situazione plausibile (altrimenti non lo avrei 
scritto), ma ad esempio con g++ 3.1 su linux ho misurato che la delete 
libera la memoria immediatamente.
Non so cosa fanno altri compilatori su altri sistemi operativi. Io ho 
usato questo test:
#include <iostream>
int main()
{
  char* ptr;
  int x;
  std::cout << "prima di allocare";
  std::cin >> x;
  ptr = new char[1000000];
  std::cout << "1 MB allocato";
  std::cin >> x;
  delete ptr;
  std::cout << "1 MB deallocato";
  std::cin >> x;
}
(ho usato cin >> x perche` era il piu` veloce da scrivere :-)
Ad ogni pausa guardavo nella process table ed effettivamente la memoria 
occupata variava "in tempo reale".


 memoria occupata variava "in tempo reale".
Ho provato il tuo codice.
Anche con il Borland C++ Compiler 5.6 su Win2000 la memoria
varia "in tempo reale".
--
Gerolamo

 occupata variava "in tempo reale".
io ho guardato non la process table, ma la memoria totale allocata.
con 1 mb variava, con 40 MB, no.
se provo a fare il touch della memoria, ovviamente si
credo che la strategia dell'allocator di sistema dipenda dal rapporto 
tra memoria libera, memoria totale, swap e memoria richiesta
#include <iostream>
#include <string>
#define MEM 40*1024*1024 
int main() {
  char* ptr;
  std::string x;
  std::cout << "prima di allocare";
  getline(std::cin,x);
  ptr = new char[MEM];
  std::cout << "40 MB allocati";
  getline(std::cin,x);
  for(int i = 0; i < MEM; ++i)
     ptr[i]=0;
  std::cout << "40 MB toccati";
  getline(std::cin,x);
  delete ptr;
  std::cout << "40 MB deallocati";
  getline(std::cin,x);
}
$ g++ -v ; uname -a
gcc version 2.95.3 
Linux localhost.localdomain 2.2.17-21mdksecure #1 SMP Thu Oct 5 12:52:38
CEST 2000 i686 unknown
ecco i risultati
  PID USER     PRI  NI  SIZE  RSS SHARE STAT %CPU %MEM   TIME COMMAND
22094 paolo     10   0   580  580   436 S     0.0  0.1   0:00 a.out
22094 paolo      5   0   592  592   440 S     0.0  0.1   0:00 a.out
22094 paolo      6   0 41552  40M   440 S     0.0  7.9   0:00 a.out
22094 paolo      4   0   588  588   440 S     0.0  0.1   0:00 a.out
che corrispondono a 
prima di allocare
40 MB allocati
40 MB toccati
40 MB deallocati

 tra memoria libera, memoria totale, swap e memoria richiesta
e` piu` che probabile: sulla mia piattaforma:
[anto@anto tmp]$ g++ -v; uname -a
Reading specs from /usr/local/lib/gcc-lib/i686-pc-linux-gnu/3.1/specs
Configured with: /usr/src/gcc-3.1/configure --enable-languages=c,c++
Thread model: single
gcc version 3.1
Linux anto.cuni.lan 2.4.18-6mdk #1 Fri Mar 15 02:59:08 CET 2002 i686 
unknown
ho provato il tuo stesso programma e ho notato che nella process table la 
memoria viene addebitata appena e` allocata, non quando e` toccata. Una 
volta deallocata viene tolta subito.
Questo conferma ancora una volta come i comportamenti 
sull'acquisizione/rilascio della memoria siano molto platform-dependent 
e quindi non ha molto senso farci affidamento, salvo situazioni molto 
particolari.


 salvo situazioni molto particolari.
A questo punto non posso che essere d'accordo.
--
Gerolamo

 particolari.
Sarebbe interessante verificare il comportamento quando la memoria e'
allocata a piccoli blocchi ( < 1kb ). E' possibile che la strategia
cambi di nuovo, ed e' comunque un comportamento piu' comune.
Ciao,
Nicola