Newsgroup: it.comp.lang.c++
Titolo: Che differenza c'è tra malloc e new?

Salve a tutti,
volevo chiedere se esiste una differenza tra malloc(.....) e  la keyword
new.
Se voglio creare una coda di oggetti, definendo la coda come una
struct coda{
          myobject  oggetto;
          struct coda *next;
                  };
typedef struct coda miacoda;
al momento di inserire il primo oggetto, dopo aver dichiarato una variabile:
miacoda queue;
devo fare queue=(miacoda*)malloc(sizeof(miacoda));
oppure
queue=new miacoda  ????
Ripeto, qual'è la differenza?
Grazie a tutti,
Sebastiano

 ha scritto nel messaggio
news:8k4oua$3th$1...@nslave1.tin.it...


Dimentichi l'aspetto fondamentale: new garantisce che vengano chiamati
gli opportuni costruttori, malloc no.
Ciao,
Nicola

 > Ripeto, qual'è la differenza?
Se cambi la dichiarazione in
    miacoda* queue;
allora la differenza e`: dopo una new, queue punta ad una
variabile di tipo miacoda, perfettamente valida (se l'autore
della classe miacoda ha fatto il suo lavoro), poiche` e`
stato eseguito il costruttore di default della classe (che
deve esistere).
Dopo una malloc, queue punta ad un blobbo di byte, non
inizializzati (piu` o meno casuali, dipende) che "dicono"
di essere una variabile di tipo miacoda, ma non lo sono
(nessun costruttore e` mai stato eseguito su di essi).
In certi casi astrusi e complessi cio` e` esattamente quel
che si desidera, allo scopo di procedere poi con un
'placement new' per l'inizializzazione (con opportuno
costruttore) della memoria precedentemente allocata.  Ma
sono casi *veramente* rarissimi.  Non occorre, di regola,
preoccuparsene minimamente.
Ecco un'eccezione.  Supponiamo di essere sulla 'critical
path' di un'applicazione real-time.  Con un buon analizzatore
di stati logici abbiamo determinato che il 'percorso critico'
richiede normalmente 7,000 istruzioni, e questo e` proprio
troppo per i vincoli RT: dobbiamo scendere a tutti i costi
a 6,000 istruzioni.
Queste sono le circostanze in cui ci si mette a caccia
anche della singola istruzione sprecata.  L'esame certosino
che in questi casi si giustifica ci mostra che parte delle
istruzioni vengono da...:
    class pippo {
        pluto plut;
        // ...
    };
    //
    void fun27() {
        pippo pip;
        // ...
    }
Viene eseguito il costruttore di default della pippo, e
questo va bene perche` esso fa il minimo necessario e le
funzioni della pip ci servono, *MA*... pippo include per
valore un pluto, quindi il costruttore di pippo implica
quello di pluto.  QUESTO costruttore si 'mangia' 250
istruzioni macchina -- e viene eseguito in media 4 volte,
di cui in media solo 1 volta serve davvero (solo una volta
pip.plut viene effettivamente USATA).  Se potessimo
costruire pip.plut solo quando serve, risparmiaremmo
750 istruzioni (3 costruttori non eseguiti a vuoto)
al costo probabilmente di poche decine di istruzioni
(i test di "vediamo se plut e` gia` inizializzata e
se no facciamolo"), un risparmio netto di 700 istruzioni
di macchina, corrispondenti a quasi un intero microsecondo,
con l'aria che tira non sarebbe male.
Come si fa...?  Il C++ permette di farlo alla grande
anche se pluto e` una classe di libreria che non si
puo` neppur pensare di alterare...:
    class pippo {
        unsigned char spazioplut[sizeof(pluto)];
        pluto& plut;
        bool plut_mustinit;
        // ...
    };
    inline pippo::pippo():
        plut(*reinterpret_cast<pluto*>(spazioplut)),
        plut_mustinit(true)
    {}
    inline void pippo::plutinit() {
        if(plut_mustinit) {
            new(&plut) pluto;
            plut_mustinit = false;
        }
    }
Ecco un uso di placement new che ha senso (in condizioni
di ottimizzazione estrema di parti veramente critiche).
Basta aggiungere la chiamata a plutinit() in ogni punto
dei metodi di pippo in cui si accede a plut, e ci siamo.
E` piu` raro immaginare condizioni cosi` incredibilmente
disperate che un'ottimizzazione-estrema del genere sia
sensata *su memoria dinamicamente allocata*; l'allocazione
dinamica, dopo tutto, e` una delle prime cose da togliere
se le prestazioni sono veramente critiche!  Comunque, non
si sa mai... i contenitori standard della libreria C++,
in particolare std::vector, usano sia l'allocazione
dinamica (attraverso un oggetto-allocatore, naturalmente;
non incorporano di certo un malloc o un new!) sia il
placement-new, in questo caso per ragioni diverse (ad
esempio, e` questo che permette di ottenere un std::vector
di oggetti che NON hanno un costruttore di default,
mentre non si potrebbe avere un *array* di oggetti privi
di costruttore di default...).
Alex

Scusate, ma se devo "mallocare" per una struct , che non è un oggetto e
quindi non ha costruttori? Che problema può darmi?
:-)
Bye

Si, volevo dichiarare un puntatore a miacoda.
Non ho mai scritto, perň, che miacoda fosse una classe.... č una "coda" di
oggetti.
Quelli si, sono di una determinata classe, ma la "miacoda" č semplicemente
un tipo costruito con una struct.
Forse non mi č chiaro questo punto, ma in C++ anche se dichiaro una struct
come in C devo fargli il costruttore?

 come in C devo fargli il costruttore?
Cosi` come per una class, se non scrivi tu esplicitamente
alcun costruttore ne genera un paio implicitamente per te
il compilatore (uno di default e uno di copia).
Alex

 quindi non ha costruttori? Che problema può darmi?
Un'istanza di struct, come un'istanza di class, i suoi costruttori
li ha eccome (se non altro quelli di default); ed e` sbagliatissimo
dire che non e` un oggetto (certo che lo e`, che altro potrebbe
essere...?!).  Se stai parlando di un oggetto POD ("Plain Old Data",
ma e` un preciso termine tecnico nello standard C++), ove il
costruttore di default si riduce in ultima analisi a lasciare
tutti i campi in stato non-inizializzato, che il costruttore
(certo puramente nozionale) sia eseguito o meno puo` non avere
importanza pratica.
Restano allora "solo" tutti gli altri problemi e limitazioni
di malloc: non ottieni un'exception in caso di fallimento, non
utilizzi eventuali ottimizzazioni/personalizzazioni di operator
new, non invochi la funzione di 'sgombero memoria' che puo`
essere stata settata con set_new_handler, e via elencando.
A fronte di tutti questi problemi e limitazioni, non riesco
a pensare a nessun vantaggio di malloc rispetto a new in
alcuna situazione pratica, con la singola ovvia eccezione
dell'allocazione di puntatori che vanno passati a vecchie
funzioni scritte in C che ne faranno poi il free (prassi assai
discutibile, ma se devi lavorare con una vecchia polverosa
libreria C che segue questo discutibile idioma, dovrai ahime`
sottostarvi, e pagare ovviamente tutti i prezzi del caso).
Alex

quindi non ha costruttori? Che problema può darmi?
Anche le struct possono avere costruttori, la differenza con le classi
e` che per default nelle struct i membri sono public.
Paolo
--------------------------------------------------
  Paolo Marotta
  Computer Science, University of Pisa
  home:   
http://www.cli.di.unipi.it/~marotta
--------------------------------------------------

Scusate, grazie per i suggerimenti. Il fatto è che sono un novello del C++
ed ancora penso alla "C".... infatti non so utilizzare la libreria STL !!!!
Per queto tenterò di implementare la coda in un modo che non usi STL

 wrote in message
news:8k763s$78g$1...@nslave1.tin.it...

Non ti consiglio di usare STL, basta e avanza la libreria standard
del C++.  Ci metti meno a imparare quel minimo che ti serve di detta
libreria, che a mettere a punto un programma che e` una selva di
puntatori...!
#include <list>
typedef std::list<quelchevuoi> lista_t;
Poi su di una qualsiasi
    lista_t l;
usi:
    l.push_back(qualcosa);    // aggiungi in coda
    l.push_front(qualcosa);   // aggiungi in testa
    l.back()...    // accedi all'oggetto di coda
    l.front()...   // accedi all'oggetto di testa
    l.pop_back();    // togli l'oggetto di coda
    l.pop_front();   // togli l'oggetto di testa
Che altro ti serve?  La libreria standard ha tutto, basta
chiedere.  Per "accedi all'oggetto" intendo, ad esempio:
    quelchevuoi x = l.back();    // copia l'oggetto di coda
    l.back().chiamaunmetodo();   // chiama un metodo
eccetera.
Se preferisci incapponirti a furia di puntatori, sappi che
i bachi ci saranno, e buon lavoro a risolverli (non postarli
qui, per favore, visto che te li stai proprio andando a
cercare tu col lanternino!).
Alex

OK!