Newsgroup: it.comp.lang.c++
Titolo: instanziare un oggetto

scusate la domanda banale
quale è la situazione in cui è utile usare
MiaClasse a;
invece di MiaClasse* b = new MiaClasse();
per instanziare un oggetto?? (e viceversa)
e come liberare poi la memoria nel primo caso??
Grazie

 ha scritto nel messaggio
news:Hns0b.17100$zN5.5...@news1.tin.it...

nel primo caso non puoi liberare la memoria ... ameno che non esci dallo
scope della tua funzione, perche' quell'istanza viene creata nello stack e
non nello heap come il caso della seconda dichiarazione ...
nel primo caso hai occupato solo la memoria per MiaClasse, nel secondo caso
hai occupato oltre allo spazio della classe anche lo spazio di un puntatore
(il puntatoore nello stack e la classe nello heap)
l'utilita e' dipendendte dal tuo programma e da che uso ne fai ...
con questo penso di aver risposto a tutte le tue domande giusto ?
ciao

 ha scritto nel messaggio
news:Hns0b.17100$zN5.5...@news1.tin.it...

Vieni da Java, vero? ;-)
La prima forma istanzia un oggetto "temporaneo", in pratica quando si esce
dallo scope in cui è definita la variabile questa viene automaticamente
distrutta; la seconda forma invece istanzia un oggetto dinamicamente: si
deve richiamare esplicitamente l'operatore delete sull'oggetto per fare modo
che la memoria occupata dall'oggetto venga effettivamente liberata.
Generalmente si usa la prima forma, a meno che non si abbia bisogno di
definire un oggetto che esista anche al di fuori dello scope in cui viene
creato.
Ciao


Ti hanno gia' risposto molto bene sulla questione lifetime; io nel mio
piccolo aggiungo che e' necessario usare il secondo sistema quando hai a che
fare con classi a derivazione.
Supponi cioe' che MiaClasse sia una classe da cui derivano MiaClasseA,
MiaClasseB... al momento opportuno *b potra' essere istanziato assumendo le
caratteristiche di MiaClasseA o B:
b= new MiaClasseA();
b= new MiaClasseB();
Saluti.

 b= new MiaClasseB();
qua' gli hai spiegato le tecniche di upcast in 2 righe ;-) non e' cosi'
semplice dirgli il perche' di questo giochetto ... poi soprattutto MiaClasse
dovrebbe essere virtuale (almeno il distruttore) seno' potresti creare
casini se uno si dimentica di fare il downcast prima di distruggere
l'elemento ...
ciao

 b= new MiaClasseB();
Polimorfismo è il termine che non ti veniva in mente ;-)
Ciao.
-- 
BSD is for UNIX lovers -- linux is for Windows haters.

 fare con classi a derivazione.
Non è vero, non è necessario usare l'allocazione dinamica per usare il
polimorfismo, è sufficiente avere dei puntatori alla classe base che puntino
ad oggetti validi, siano essi sullo stack o sullo heap.
Ciao

 Ciao.
Rispondo a tutti e 3:
1) (HPI) Ho preferito fornire un esempio, poi se il termine polimorfismo e'
noto, anche meglio...
2) (GOUL)  E' chiaro che le cose sono piu' complesse di come le ho descritte
ed occorre tutto un paradigma necessario nella costruzione della classe base
e derivate (distruttori virtuali, ecc. ecc.).
3) (WONDERBOY) devi sempre usare puntatori, in ogni caso. E comunque il mio
era proprio un esempio classico, con tutte le eccezioni del caso.
Saluti.
Saluti.

 3) (WONDERBOY) devi sempre usare puntatori, in ogni caso.
Puoi anche usare i reference...


 era proprio un esempio classico, con tutte le eccezioni del caso.
Su questo son d'accordo, ma la domanda dell'OP era esplicitamente diretta
all'utilizzo della memoria dinamica, quindi forse era il caso di spiegare
meglio il concetto. Inoltre, come ha osservato HPL, si possono usare anche i
reference.
Ciao

 Puoi anche usare i reference...
E' vero.
Saluti.

 Ciao
ecco appunto, che sono i reference.
Per me il riferimento èsempre stato passare l'indirizzo di un oggetto ma mi
sembra di capire che in C++ esistono 3 modi di passare parametri

 ha scritto nel messaggio
news:sj%0b.22345$zN5.6...@news1.tin.it...

I reference sono praticamente dei puntatori autoreferenzianti (a volte li
chiamano "alias"), ad esempio:
int a = 4;
int &b = a; // definisce un riferimento ad a
ora in pratica a e b sono due nomi distinti per lo stesso oggetto,
manipolando l'uno si modifica anche l'altro; occhio che non è possibile
riassegnare un reference.
Passare un argomento ad una funzione per riferimento ha lo stesso effetto
del passaggio per indirizzo (nel senso che dall'interno si può modificare la
variabile esterna), oppure come parametro di ritorno se si vuole usare la
concatenazione: ad esempio, operator<< per std::cout ritorna uno
std::ostream &, ed è per questo motivo che puoi concatenare <<:
std::cout << "ciao" << std::endl;
Ciao

 std::cout << "ciao" << std::endl;
io ci sto sbattendo un po la testa per capire bene i ritorni delle funzioni
e quando essi vengono auto distrutti o richiedono la distruzione o come
alcuni di network sono statici e bisogna stare attenti se si usano i thread
...
in questo caso ritorni un reference ad un ostream& ma dopo il suo uso viene
auto distrutto ? o come funziona l'ambaradan ?
ciao

 come mai non da la possibilita' di riassegnare un riferimento ??? 
Perchè tra i valori "validi" per un puntatore c'è il valore 0 (NULL), che 
appunto è quel valore che i riferimenti dovrebbero poter evitare a 
compile-time.
-- 
---
*************** | Have you ever retired a human by mystake?
*** Azathot *** |
*************** | To contact me, ask me gently. Thanks.

 Sorry, mi sbaglio sempre, e dire che ti vedo spesso. Lovecraft suppongo ;)
y


 sembra di capire che in C++ esistono 3 modi di passare parametri
Non è esatto; in C++ esistono *due* modi di passare parametri: per
riferimento (mediante i reference, appunto) e per valore.
Un esempio:
void f (int a); //passaggio per valore
void f (int* a); //passaggio per valore
void f (int& a); //passaggio per riferimento


 compile-time.
ok ... ma cosi non si puo' usare magari in un ciclo b = a[i] dove b e' un
int &b;
esempio stupido ... ma e' la prima cosa che mi e' venuta in mente ...
cmq visto che l'uso piu' comeune e' in dichiarazione di funzione se uno ci
passa un oggetto nullo ???
tipo un *a dove a e' un oggetto *a; ?
ciao e grazie dei chiarimenti ... si capisce di piu' da questi dialoghi che
dai libri soprattutto negli usi dove il libro ha pochi esempi ...

 void f (int* a); //passaggio per valore
questo noi lo chiamavamo per puntatore ... o diretto ...
ciao

 passa un oggetto nullo ???
Non è possibile (pena errore di compilazione) dereferenziare un valore 
nullo. Es:
        f( const Classe& _pippo );
        ...
        f( *NULL ); // ERRORE DI COMPILAZIONE
        ...
Ovviamente, rimane ancora possibile effettuare qualcosa del tipo:
        Classe * x = NULL;
        ...
        f( *x );
che non verrebbe sanzionato dal compilatore... ma d'altro canto ci dobbiamo 
difendere da Murphy non ma Macchiavelli... ;-)
Ciao.


 tipo un *a dove a e' un oggetto *a; ?
???
        Mauro

 writes:

Allora esistono infiniti modi:
void f( int a );  // per valore
void f( int& a ); // per riferimento
void f( int* a );  // per puntatore
void f( int*& a ); // per riferimento a puntatore
void f( int** a ); // per puntatore a puntatore
void f( int**& a );
...
void f( int************************** a ); 
...
senza contare smart pointer e classi proxy.
        Mauro

 void f( int*& a ); // per riferimento a puntatore
ha tolto il sonno..
"odio * e & ecco perchè non imparerò ma il c++"

 ha tolto il sonno..
I puntatori, come gli altri oggetti, possono essere passati sia per
valore che per riferimento.
Se T e` un tipo,  "void f( T& a )"  e` una funzione che prede un
parametro di tipo T passato per riferimento. Es:
  void f( int& a );      // intero per rif.
  void f( double& a );   // double per rif.
  void f( int*& a );     // puntatore a intero (int*) per rif.
 
  typedef int* pointer;
  void f( pointer& a);   // stessa cosa
        Mauro

 questo noi lo chiamavamo per puntatore ... o diretto ...
Questo è semplicemente un passaggio per valore.


 void f( int*& a ); // per riferimento a puntatore
E qui un puntatore, per riferimento.
Saluti.

 Cos'e` un oggetto nullo?
questo ...
func (int &b) ...
int *a = NULL;
func (*a);
ciao

 senza contare smart pointer e classi proxy.
lasciando fuori questi ultimi ...
la prima serie e' solo l'implementazione ricorsiva dei primi 3 modi ...
(anzi solo 2 perche' non ri puo' passare in serie per valore :-p)
ciao

 Non e' "per" puntatore, qui passi un puntatore . Per valore.
e' sbagliato vederlo per valore ... perche' l'informazione utile alla
funzione e' un int il puntatore non e' la sua informazione quindi per forza
di cose non puoi dire che gli hai passato un valore ... quel valore e' un
puntatore a dove prendere il valore che veramente gli serve ... ecco perche'
per i miei insegnamenti e perche' ho questa forma mentis ormai sono 3
differenti tipi ...
ciao

 Questo è semplicemente un passaggio per valore.
leggiti l'altro mex ... per me' logicamente lo vedo ormai come un 3
differente tipo ... sbagliato per sbagliato questo modo mi dice in lettura
dove sto sbagliando l'uso di qualcosa ...
ciao

 func (*a);
Tentando di dereferenziare un puntatore nullo si ottiene undefined
behaviour, non un oggetto nullo.
        Mauro

 perche' ho questa forma mentis ormai sono 3 differenti tipi ...
Se consideri il modo in cui viene passato il parametro, esistono solo
2 modi: valore e riferimento. (Nell'esempio il parametro e` a di tipo
int* e viene passato per valore.)
Se consideri il modo in cui la funzione usa i parametri per trovare
tutte le informazioni che le servono, esistono piu` di 3 modi (i nomi
sono inventati sul momento):
void f(int x) {}   // diretto
void f(int* p) { int x = *p; ... }  // per puntatore
void f(T::iterator i) { int x = *i; ... } // per iteratore
void f(int i) { int x = info[i]; ... } // per indice
void f(string s) { int x = info_map[s]; ... } // per chiave
void f(T::iterator i1, T::iterator i2) // per coppia di iteratori
{ while (i1 != i2) int x = *i1++; ... }
template <typename T>
void f(T a) { int x = info<T>::value; ... } // per tipo
...
In tutti questi casi i parametri possono essere passati per valore o
per riferimento.
       Mauro

 ha scritto nel messaggio
news:87fzjtt...@iperbole.bologna.it...
erano solo esempi ...
cmq ho capito benissimo gli usi ... non sono errori miei ... era solo per
fare un po di polemica del come mai non dare la possibilita' di manipolare
altre cose ...
ciao

 dove sto sbagliando l'uso di qualcosa ...
Beh, nessuno ti può impedire di pensarla come vuoi, l'importante è che
tu sappia che sono realmente le cose.


 funzione e' un int il puntatore non e' la sua informazione
E chi lo ha detto? Non potresti essere interessato al valore di quel
puntatore?
E comunque formalmente e' un passaggio per valore di un tipo int*, non vedo
perche' costruiure un caso in piu' quando la visione piu' generale mi sembra
quella a 2 modi.
Saluti

 tu sappia che sono realmente le cose.
Ho come un dejavu per questo ultimo dibattito... ricordi? ;)
Saluti.

 Ho come un dejavu per questo ultimo dibattito... ricordi? ;)
Già...


 Già...
??????
io non capisco ...
ciao

 io non capisco ...
C'era stata a proposito una lunga discussione su un altro ng.
