Newsgroup: it.comp.lang.c++
Titolo: pro e contro dell'allocazione dinamica...

Ho una classe A che, tra le altre cose, "contiene" alcuni oggetti di tipo B
e C.
Per includere gli oggetti B e C potrei dichiarare degli adatti puntatori ed
utilizzare new....
B* pB;
pB = new B .... ecc. ecc.
oppure potrei semplicemente utilizzarli direttamente
B b1;
B b2; ecc. ecc.
Quali sono i pro e i contro delle due soluzioni??
Ciao a tutti
Andrea

 Andrea
I pro sone che se gli oggetti contengono funzioni virtuali,potrai avvalerti
del polimorfismo di tali oggetti,pero' dovrai poi ricordarti di dsitruggere
esplicitamente l'oggetto,cosa che puoi trascurare se non utilizzi puntatori.
Un altra cosa che mi viene in mente a favore dell'utilizzo di puntatori,e'
l'alleggerimento dello stack,soprattutto se gli oggetti in questione sono di
grandi dimensioni.
--
Ivan Molella
__LINUX__ the choice of the __GNU__ generation
icq# 97960484

Vantaggi dell'allocazione dinamica:
a) maggiore flessibilita`, (es. l'oggetto contenuto potrebbe essere
tanto di classe base quanto di classe derivata);
b) Non sempre e` immediatamente noto quale oggetto
deve essere esattamente contenuto o quali sono
i parametri necessari alla sua costruzione (es. potrebbero
derivare da complesse operazioni di I/O), il contenimento indiretto
consente una costruzione in piu` fasi e una piu` corretta implementazione
dell'idioma "l'inizializzazione e` acquisizione".
c) possibilita` di implementare tecniche di reference counting
d) possibilita` di implementare relazioni 1-n (anche se cio` e` spesso
facilmente fattibile anche con il contenimento diretto
di strutture della libreria standard o comunque di strutture dinamiche sul 
modello
di vector<> o list<>).
Vantaggi dell'allocazione statica:
a) L'accesso alle componenti non deve passare per un livello
di indirezione (il che non significa solo e semplicemente
maggiori prestazioni).
b) Non e` necessario allocare e deallocare esplicitamente risorse
(tuttavia i contenitori standard solitamente eliminano questo vantaggio).
c) Controllo di tipo piu` precisi e possibilita` che il compilatore espanda le
funzioni virtuali dichiarate anche inline.
d) E` piu` semplice realizzare applicazioni exception safe
Paolo
--
Paolo Marotta
Duck Communication Entertainment s.r.l.
Largo Arenula, 11 - Roma
http://www.duckce.com
p.ma...@duckce.com
-- 
Posted from 
HA-server-a.cs.interbusiness.it
 [151.99.250.31] 
via Mailgate.ORG Server - 
http://www.Mailgate.ORG

grandi dimensioni.
Non ho compreso il commento sullo stack... riguardo alla domanda
dell'OP a me viene anche in mente che utilizzando dei puntatori
nella classe "contenitore" si ottiene una semantica diversa per
il costruttore di copia e l'operatore di assegnazione creati
automaticamente dal compilatore.
   class A
   {
     private:
       class B *b;
     public:
       A() : b(new B)
       { }
       ~A()
       {
         delete b;
       }
   };
Questa classe contiene un problema potenziale... il distruttore si
comporta come se A fosse l'unico proprietario dell'oggetto B
contenuto ma si dimentica di implementare il copy constructor e
l'operatore di assegnazione...
    A a1,a2;
    a1=a2;    // Disastro: object leak e doppia distruzione di
              // una istanza di B
    A a3(a1); // Stesso problema con copy constructor
    void f(A x);
    f(a1);    // Stesso problema: viene fatta una copia implicita
              // di a1 con conseguente disastro
Una regola semplice da ricordare e' la legge dei tre: distruttore,
costruttore di copia e operatore di assegnazione lavorano quasi
sempre assieme... se hai bisogno di uno allora molto probabilmente
hai bisogno di tutti e tre.
Se nello specifico non sei interessato a operazioni di assegnazione
o costruzioni di copia allora e' meglio impedire che vengano usate:
   class A
   {
     private:
       class B *b;
       A(const A& other);            // solo dichiarazione
       A& operator=(const A& other); // solo dichiarazione
     public:
       A() : b(new B)
       { }
       ~A()
       {
         delete b;
       }
   };
In questo modo eventuali tentativi di usare le operazioni non
corrette saranno segnalate dal compilatore (come violazione
dell'incapsulamento se si prova a usarle da "fuori" e con
errori di link se si usano inavvertitamente nell'implementazione
dei metodi dell'oggetto).
HTH
Andrea
--
Andrea Griffini, Programmer
http://www.netservers.com/~agriff

 Non ho compreso il commento sullo stack...
data:
class a { ....... } obj,*pt_obj;
sizeof(obj) "in genere" e' maggiore di sizeof(pt_obj),e' questo in un'area di
memoria limitata come lo stack,puo' fare la differenza soprattutto in
funzioni ricorsive, e in programmazione di codice  kernel.



ed il problema opposto?? si sente di tanto in tanto parlare di
"frammentazione dello heap" ...... e' un problema reale o e' piu' una
leggenda metropolitana? A me non e' mai capitato di batterci il naso ma ....
c'e' sempre una prima volta ;-)
Andrea

 di vector<> o list<>).
io aggiungerei:
e) Posso istanziare un oggetto in una classe e distrugerlo in un altra senza
    necessità di copiare l'oggetto.
f) nel caso di incapsulamento non devo conoscere a priori la dimensione
della classe puntata (posso usare così
   una salutare forward declaration).
g) posso costruire l'istanza dell'oggetto puntato solo se e quando serve
(ovviamente devo inizializzare almeno a zero
    il puntatore).

 >ed il problema opposto?? si sente di tanto in tanto parlare di
 >"frammentazione dello heap" ...... e' un problema reale o e' piu' una
 >leggenda metropolitana?
Il problema esiste, ma non e` una cosa che si verifica in ogni
applicazione.
