Newsgroup: it.comp.lang.c++
Titolo: I libri mentono...

Cari amici, chi vi scrive è uno di voi, certo all'inizio della 'carriera',
ma con la vostra stessa voglia di farcela.
Vi scrivo perché nello studiare il C++, in particolare riguardo alle
funzioni costruttori e distruttori, ho scoperto qualcosa di molto strano.
Qui di seguito vi è del semplicissimo codice c++ che mette in evidenzsa
quello che vi dirò:
#include <iostream.h>
class prova {
public:
prova(){cout<<"\ncostruttore standard";}
~prova(){cout<<"\ndistruttore standard";}
};
prova f1(){ prova temp; return temp;}
//crea un oggetto e lo restituisce come risultato della funzione
int main()
{
prova ob1;  //chiama il primo costruttore
ob1=f1();
return 0;
}
bene se provate ad eseguire questo codice vi ritroverete con due funzioni
costruttore (giusto) ma ben 3 funzioni distruttore!
Ora mi rivolgo a Voi che probabilmente ci siete passati prima di me, perché
avviene questo?
Io personalmente, avendo molta fantasia, ho elaborato queste teorie:
-Un errore del compilatore, soluzione che semplificherebbe molte cose, ma
alquanto strana vista la situazione in cui si verifica
-Può essere capitato questo: sappiamo che una variabile locale esiste
all'interno del blocco che la dichiarata fino a quando non si esce da quel
blocco.
Bene sappiamo pure che ci hanno insegnato ( a dire il vero quasi tutti lo
abbiamo imparato da soli sui libri..ma non tergiversiamo) che quando una
funzione restituisce un valore il procedimento è quello di assegnare il
valore della funzione (praticamente la variabile associata alla istruzione
di return) alla variabile del main che deve contenere il valore della
funzione e poi la variabile locale alla funzione che rappresenta il valore
viene distrutta.
Bene secondo me vi sono delle incongruenze.
Mi è stata insegnata questa regola: le variabili locali ALL'USCITA della
funzione      (praticamente quando si giunge all'istruzione return)
vengono distrutte..quindi come facciamo a dire  che quando una funzione
restituisce un valore questo valore    (variabile locale alla funzione)
viene assegnato alla variabile del main (per esempio)  per  poi essere
distrutta?
Le cose potrebbero andare così, lo so potrà sembrare assurdo ma è l'unica
spiegazione che mi sono riuscito a dare per quanto riguarda i tre
distruttori riferiti a due oggetti.
Possiamo pensare che all'uscita di una funzione (quando si giunge al return)
la variabile associata al return, che poi è il valore della funzione venga
distrutta come tutte le altre varibili locali, solo che a differenza di
quest'ultime, dovendo "esportare" il risultato della funzione, il suo valore
venga copiato in un 'ALTRA variabile, che possiamo chiamare variabile ghost.
Bene è in realtà questa variabile ghost che viene assegnata alla variabile
del main PER POI essere distrutta.
Lo so è assurdo, ma questo discorso per quanto strano si può applicare a
qualunque funzione che restituisce qualunque tipo di risultato, e
spiegherebbe perché per due oggetti abbiamo 3 distruttori.
Amici miei SVELIAMO IL MISTERO, ho fiducia in Voi,
Saluti
Micky De Sortis

Amici miei SVELIAMO IL MISTERO, ho fiducia in Voi,
Oltre al costruttore che hai definito tu il C++ ne ha
generato un'altro implicitamente, chiamato costruttore
di copia, che viene utilizzato per copiare il contenuto
di "temp" nella variabile temporanea senza nome che
conterra' il valore di ritorno della funzione.
Questa variabile senza nome viene poi utilizzata per
effettuare l'assegnazione a obj1 e viene infine
distutta.
Questo costruttore di copia ha la dichiarazione
   prova(const prova& o);
Se provvederai a definire anche il costruttore
di copia esplicitamente ti accorgerai che il
conteggio di costruttori/distruttori quadra.
HTH
Andrea
--
Andrea Griffini, Programmer
http://www.netservers.com/~agriff

 [CUT]
Prova con:
#include <iostream>
class prova
{
  public:
      prova()
      {
       std::cout << "\ncostruttore standard";
      }
      prova(const prova&)
      {
       std::cout << "\ncostruttore di copie";
      }
      ~prova()
      {
       std::cout << "\ndistruttore standard";
      }
};
f1() e main() invariate.
Poi prova a modificare f() in questo modo:
prova f1()
{
   return prova();
}
Infine prova a modificare main in questo modo:
int main()
{
   prova ob1 = f1();
}
Manlio Perillo

 
http://www.netservers.com/~agriff
Innanzitutto, Andrea, grazie per avermi risposto, ma ti devo dire che non
sono molto convinto, e ti spiego il perché.
Mi pare strano che il c++ faccia alcune cose "implicitamente", o le fa
perchè le diciamo noi o non le fa.
Per quanto riguarda il costruttore di copie, ne ero a conoscenza e nel caso
originario che volevo sottoporre era presente ma poi l'ho tolto in quanto
non risolveva niente del problema, e ti spiego il perchè.
Ammesso pure che il c++ crei implicitamente un costruttore di copie (senza
offesa, sarebbe anche sciocca una cosa del genere, perchè altrimenti che
cosa lo impariamo a fare il costruttore se viene sempre implicitamente
chiamato? Io so, e sicuramente lo sai anche tu,che quando non c'è viene
eseguita una copia bit a bit) questo non risolverebbe un bel niente essendo
il costruttore di copie innanzitutto un costruttore e quindi come tale non
restituisce nessun valore, e avendo nella dichiarazione sebbene un oggetto
di tipo prova ,  questo è    un parametro  indirizzo!. cioè praticamente un
puntatore implicito e come tale non crea e non distrugge proprio niente,
rappresenta solo un riferimento.
Caro Andrea, comunque siamo arrivati a un punto d'incontro e cioè che anche
tu ammetti l'esistenza di una variabile          'senza nome'       che
contiene il valore restituito dalla funzione, (praticamente la variabile
associata al return all'uscita dalla funzione viene distrutta come tutte le
altre variabili locali), quindi tale variabile NEL MAIN (perché giunti nel
main vuol dire che siamo usciti dalla funzione e che quindi tutte le
variabili locali a questa sono andate distrutte) verrebbe assegnata
all'oggetto che deve contenere il risultato della funzione, e SOLO ORA
verrebbe distrutta.
Il discorso di base è questo c'è una variabile 'senza nome' per te,
variabile 'ghost' per me, che praticamente è una copia della variabile che
rappresenta il risultato della funzione. Questa era qualcosa che normalmente
non avremmo mai potuto vedere, ma è uscita fuori grazie ai distruttori.
Caro Andrea, e mi rivolgo anche a tutti gli atri, cerchiamo di risolvere
questo schifo di fatto, la verità è vicina, sarà pure una stupidaggine ma
non mi va di imparare qualcosa che non so governare.
Ecco perché dico i libri mentono...o almeno non la dicono tutta.
Grazie e ci si sente.
Micky De Sortis

Grazie a tutti per la collaborazione, chi avrà ragione vincerà.

Ecco perché dico i libri mentono...o almeno non la dicono tutta.
I libri che ho letto mi hanno sempre fornito spiegazioni esaurienti
che giustificavano i comportamenti che rilevavo. Ovviamente non ho
idea di quali siano i libri che hai letto tu e quindi non so cosa
dirti (sicuramente in questo momento c'e' un sacco di robaccia
in circolazione). Tu a quali libri esattamente ti riferisci ?
So ad esempio che i testi di Schildt sono famosi per fornire
informazioni fasulle.
Io ti consiglierei di leggere qualcuno dei testi che trovi elencati
nella FAQ del canale; sono convinto che su questi concetti cardine
non siano lacunosi o depistanti.
Soprattutto pero' ti consiglio caldamente di evitare di farti una
base con corsi presentati sulle riviste; purtroppo a scrivere
mettono a volte gente senza competenza e con le idee molto confuse.
Inoltre il controllo di qualita' degli editori in questo campo e'
TOTALMENTE ASSENTE.
Se sei fortunato ti capita un articolo scritto da una persona
in gamba, se sei sfortunato il contenuto non fara' altro che
aumentare la confusione e la disinformazione (e per chi si sta
avvicinando ad un argomento forse non e' facile discriminare).
Se ti interessa ho raccontato dettagliatamente una mia esperienza
con questi articolisti da combattimento sulla mia homepage
(sezione "fumo e arrosto").


non mi va di imparare qualcosa che non so governare.
La verità te la ha già detta Andrea, il problema è nel copy ctor.
Anto

distrutta?
Chiaramente il valore ritornato deve sopravvivere per un po' alla
return, in particolare la sua sopravvivenza mi pare sia garantita
per il tempo necessario a valutare l'intera espressione in
cui il temporaneo appare.
Paolo
-------------------------------------------
  Paolo Marotta
 
http://web.tiscalinet.it/paolo_marotta/
-------------------------------------------

Ecco perché dico i libri mentono...o almeno non la dicono tutta.
Che libri leggi?
Non so che libri leggi, ma queste sono cose ben documentate
e arcinote.


3(+1) costruttori, 3(+1) distruttori.
3+3



infatti anche secondo me č cosě.
Ma tutti i compilatori attuali supportano la RVO ?

Ma tutti i compilatori attuali supportano la RVO ?
Direi di no, a meno di non aver capito male il
senso di tale ottimizzazione.
La mia prova l'ho fatta con il solito VC++ e dai
risultati direi che non ha ottimizzato troppo (a meno
di miei errati settaggi).


}