In quali casi utilizzo malloc e / o new?


479

Vedo in C ++ che ci sono diversi modi per allocare e liberare dati e capisco che quando chiami mallocdovresti chiamare freee quando usi l' newoperatore dovresti accoppiarti deleteed è un errore mescolare i due (es. Chiamare free()su qualcosa che è stato creato con l' newoperatore), ma non sono chiaro quando dovrei usare malloc/ freee quando dovrei usare new/ deletenei miei programmi del mondo reale.

Se sei un esperto di C ++, per favore fammi sapere eventuali regole pratiche o convenzioni che segui al riguardo.


33
Vorrei solo aggiungere un promemoria sul fatto che non è possibile mescolare i due stili, ovvero non è possibile utilizzare new per creare un oggetto e quindi chiamare free () su di esso, né tentare di eliminare un blocco allocato da malloc (). Probabilmente ovvio dirlo, ma nondimeno ...
oggi

32
Buone risposte, tutto quello che devo aggiungere (che non ho visto) è che new / delete chiama il costruttore / distruttore per te, malloc / free no. Solo una differenza degna di nota.
Bill K,

Con il moderno C ++, sto ancora cercando di trovare un motivo per usarlo.
Rahly,

Oppure non utilizzare nessuno dei due e andare con std: shared_ptr <T>. Quindi non è necessario eliminare affatto.
Vincent,

Risposte:


387

A meno che non sei costretto a usare C, non dovresti mai usare malloc . Usa sempre new.

Se hai bisogno di una grande mole di dati, fai qualcosa come:

char *pBuffer = new char[1024];

Fai attenzione anche se questo non è corretto:

//This is incorrect - may delete only one element, may corrupt the heap, or worse...
delete pBuffer;

Invece dovresti farlo quando elimini un array di dati:

//This deletes all items in the array
delete[] pBuffer;

La newparola chiave è il modo C ++ per farlo e farà in modo che il tuo tipo abbia il suo costruttore chiamato . La newparola chiave è anche più sicura, mentre mallocnon è affatto sicura.

L'unico modo in cui potrei pensare che sarebbe utile usarlo mallocsarebbe se avessi bisogno di cambiare la dimensione del tuo buffer di dati. La newparola chiave non ha un modo analogo come realloc. La reallocfunzione potrebbe essere in grado di estendere le dimensioni di un pezzo di memoria per te in modo più efficiente.

Vale la pena ricordare che non è possibile mescolare new/ freee malloc/ delete.

Nota: alcune risposte a questa domanda non sono valide.

int* p_scalar = new int(5);  // Does not create 5 elements, but initializes to 5
int* p_array  = new int[5];  // Creates 5 elements

2
Per quanto riguarda la chiamata di eliminare foo quando dovresti chiamare delete [] foo, alcuni compilatori lo ripareranno automaticamente per te e non perderanno e altri elimineranno solo la prima voce e perderanno. Ne ho avute alcune in qualche codice e valgrind le troverà per te.
KPexEA,

30
Se non si utilizza l'eliminazione corretta, il risultato non è definito . Non è corretto. Il fatto che possa ottenere una parte della cosa giusta o funzionare a volte è solo una fortuna cieca.
Michael Burr,

8
@KPexEA: anche se alcuni compilatori potrebbero correggere i tuoi errori, è comunque sbagliato farli in primo luogo :) Usa sempre delete [] dove appropriato.
korona,

62
"A meno che tu non sia costretto a usare C, non dovresti mai usare malloc. Usa sempre nuovo." Perché? Qual è la vittoria qui? Per gli oggetti che necessitano di costruzione, ma per i blocchi di memoria, si documentano chiaramente due modi per commettere errori di codifica (più facilmente catturati () vs [] in nuovi e meno facilmente catturati array vs scaler nuovi ed eliminati). Qual è la motivazione per usare new / delete per blocchi di memoria grezza?
Ben Supnik,

3
@DeadMG: se si sta creando un array da utilizzare con una funzione API asincrona, non new[]sarebbe molto più sicuro di std::vector? Se si usa new[], l'unico modo in cui il puntatore diventerebbe non valido sarebbe tramite esplicito delete, mentre la memoria allocata per un std::vectorpotrebbe essere invalidata quando il vettore viene ridimensionato o lascia l'ambito. (Si noti che quando si utilizza new[]uno dovrebbe consentire la possibilità che uno potrebbe non essere in grado di chiamare deletese il metodo asincrono è ancora in sospeso; se potrebbe essere necessario abbandonare un'operazione asincrona, potrebbe essere necessario organizzare l'eliminazione tramite callback) .
supercat,

144

La risposta breve è: non utilizzare mallocper C ++ senza una ragione davvero valida per farlo. mallocpresenta una serie di carenze quando viene utilizzato con C ++, che è newstato definito per superare.

Carenze risolte da nuove per il codice C ++

  1. mallocnon è dattiloscritto in alcun modo significativo. In C ++ devi eseguire il cast del ritorno da void*. Questo potenzialmente introduce molti problemi:

    #include <stdlib.h>
    
    struct foo {
      double d[5];
    }; 
    
    int main() {
      foo *f1 = malloc(1); // error, no cast
      foo *f2 = static_cast<foo*>(malloc(sizeof(foo)));
      foo *f3 = static_cast<foo*>(malloc(1)); // No error, bad
    }
    
  2. È peggio di così però. Se il tipo in questione è POD (semplici vecchi dati), è possibile utilizzarlo in modo semi-sensibile mallocper allocare memoria, come f2nel primo esempio.

    Non è così ovvio se un tipo è POD. Il fatto che sia possibile che un determinato tipo passi da POD a non-POD senza errori di compilazione risultanti e problemi potenzialmente molto difficili da eseguire il debug è un fattore significativo. Ad esempio, se qualcuno (forse un altro programmatore, durante la manutenzione, molto più tardi dovesse apportare una modifica che non causava foopiù il POD, al momento della compilazione non apparirebbe alcun errore evidente come speravi, ad esempio:

    struct foo {
      double d[5];
      virtual ~foo() { }
    };
    

    renderebbe la mallocdel f2cattivo diventare anche, senza alcuna diagnosi evidenti. L'esempio qui è banale, ma è possibile introdurre accidentalmente non-PODness molto più lontano (ad esempio in una classe base, aggiungendo un membro non-POD). Se si dispone di C ++ 11 / boost, è possibile utilizzare is_podper verificare che questo presupposto sia corretto e generare un errore se non lo è:

    #include <type_traits>
    #include <stdlib.h>
    
    foo *safe_foo_malloc() {
      static_assert(std::is_pod<foo>::value, "foo must be POD");
      return static_cast<foo*>(malloc(sizeof(foo)));
    }
    

    Sebbene boost non sia in grado di determinare se un tipo è POD senza C ++ 11 o altre estensioni del compilatore.

  3. mallocritorna NULLse l'allocazione fallisce. newgetterà std::bad_alloc. Il comportamento dell'utilizzo successivo di un NULLpuntatore non è definito. Un'eccezione ha una semantica pulita quando viene generata e viene generata dalla fonte dell'errore. Avvolgere malloccon un test appropriato ad ogni chiamata sembra noioso e soggetto a errori. (Devi solo dimenticare una volta per annullare tutto quel buon lavoro). È possibile consentire a un'eccezione di propagarsi a un livello in cui un chiamante è in grado di elaborarlo in modo NULLsensato , dove è molto più difficile restituire in modo significativo. Potremmo estendere la nostra safe_foo_mallocfunzione per lanciare un'eccezione o uscire dal programma o chiamare un gestore:

    #include <type_traits>
    #include <stdlib.h>
    
    void my_malloc_failed_handler();
    
    foo *safe_foo_malloc() {
      static_assert(std::is_pod<foo>::value, "foo must be POD");
      foo *mem = static_cast<foo*>(malloc(sizeof(foo)));
      if (!mem) {
         my_malloc_failed_handler();
         // or throw ...
      }
      return mem;
    }
  4. Fondamentalmente mallocè una funzionalità C ed newè una funzionalità C ++. Di conseguenza malloc, non gioca bene con i costruttori, ma considera solo l'allocazione di una parte di byte. Potremmo estendere safe_foo_malloculteriormente il nostro utilizzo al posizionamento new:

    #include <stdlib.h>
    #include <new>
    
    void my_malloc_failed_handler();
    
    foo *safe_foo_malloc() {
      void *mem = malloc(sizeof(foo));
      if (!mem) {
         my_malloc_failed_handler();
         // or throw ...
      }
      return new (mem)foo();
    }
  5. La nostra safe_foo_mallocfunzione non è molto generica - idealmente vorremmo qualcosa in grado di gestire qualsiasi tipo, non solo foo. Possiamo raggiungere questo obiettivo con modelli e modelli variabili per costruttori non predefiniti:

    #include <functional>
    #include <new>
    #include <stdlib.h>
    
    void my_malloc_failed_handler();
    
    template <typename T>
    struct alloc {
      template <typename ...Args>
      static T *safe_malloc(Args&&... args) {
        void *mem = malloc(sizeof(T));
        if (!mem) {
           my_malloc_failed_handler();
           // or throw ...
        }
        return new (mem)T(std::forward(args)...);
      }
    };

    Ora, sebbene risolvendo tutti i problemi che abbiamo identificato finora, abbiamo praticamente reinventato l' newoperatore predefinito . Se hai intenzione di utilizzare malloce posizionare, newallora potresti anche usare newper cominciare!


27
Peccato che C ++ sia prodotto structe classsignifichi sostanzialmente la stessa cosa; Mi chiedo se ci sarebbero stati problemi con l' structessere riservati ai POD e possibilmente avere tutti i classtipi presunti come non-POD. Qualsiasi tipo definito dal codice che ha preceduto l'invenzione del C ++ sarebbe necessariamente un POD, quindi non credo che la compatibilità con le versioni precedenti sia un problema. Ci sono vantaggi nel far dichiarare i tipi non POD come structpiuttosto che class?
supercat,

1
@supercat Un po 'tardi, ma a quanto pare, fare structe classfare quasi la stessa cosa è stata una meravigliosa decisione di progettazione che ora abilita una caratteristica ordinata chiamata "metaclassi" (da Herb) .
Rakete1111,

@ Rakete1111: A prima vista, quella proposta sembra preelaborare una versione del linguaggio che utilizza parole chiave con prefisso in dollari come $class. Io non sono sicuro di quello che ha a che fare con classe structche sono sinonimi, tuttavia.
Supercat,

@supercat Il sistema di tipi sarebbe stato biforcato di più. Avendo classe structintendendo efficacemente la stessa cosa, puoi fare trasformazioni arbitrarie su di esse ( $class) senza preoccuparti di creare una classa structe viceversa.
Rakete1111,

@ Rakete1111: se alcuni tipi di operazioni e trasformazioni sono al sicuro con alcuni tipi, ma non con altri, se il tipo lo identifica direttamente e se un compilatore rifiuta operazioni e trasformazioni non sicure, sembrerebbe meglio che avere una modifica a una metaclasse utilizzata in modi che sono adatti solo per un PODS, vengono silenziosamente cambiati in un non-PODS.
supercat

53

Dal C ++ FQA Lite :

[16.4] Perché dovrei usare new invece di trustworthy old malloc ()?

FAQ: nuovo / cancella chiama il costruttore / distruttore; nuovo è sicuro, malloc no; nuovo può essere ignorato da una classe.

FQA: Le virtù della nuova menzionata dalle FAQ non sono virtù, perché costruttori, distruttori e sovraccarico dell'operatore sono spazzatura (vedi cosa succede quando non si ha la spazzatura?), E qui il problema della sicurezza del tipo è davvero minuscolo (normalmente hai per lanciare il vuoto * restituito da malloc al tipo di puntatore destro per assegnarlo a una variabile di puntatore tipizzata, che può essere fastidiosa, ma tutt'altro che "non sicura").

Oh, e l'utilizzo del vecchio malloc affidabile rende possibile l'uso del realloc altrettanto affidabile e vecchio. Peccato che non abbiamo un nuovo operatore lucido rinnovabile o qualcosa del genere.

Tuttavia, il nuovo non è abbastanza grave da giustificare una deviazione dallo stile comune usato in una lingua, anche quando la lingua è C ++. In particolare, le classi con costruttori non banali si comporteranno in modo fatale se semplicemente malifichi gli oggetti. Quindi perché non usare nuovi in ​​tutto il codice? Le persone raramente sovraccaricano l'operatore nuovo, quindi probabilmente non ti ostacolerà troppo. E se sovraccaricano di nuovo, puoi sempre chiedere loro di smettere.

Mi dispiace, non ho potuto resistere. :)


7
Questa è una rivolta ! Grazie.
dmckee --- ex gattino moderatore,

8
Non posso prendere sul serio questo commento poiché proietta chiaramente la parte dell'autore nei confronti del C ++. Il C ++ è un linguaggio utilizzato per creare software orientato alle prestazioni e un garbage collector potrebbe essere dannoso solo per il suo obiettivo. Non sono d'accordo con la tua intera risposta!
Miguel,

1
@Miguel Ti sei perso la battuta.
Dan Bechard,

50

Usa sempre nuovo in C ++. Se è necessario un blocco di memoria non tipizzata, è possibile utilizzare direttamente l'operatore new:

void *p = operator new(size);
   ...
operator delete(p);

3
interessante, ho sempre assegnato una matrice di caratteri non firmati quando ho bisogno di un buffer di dati non elaborati come questo.
Greg Rogers,

Attenzione la semmantica dovrebbe essere così: p_var = new type (inizializzatore); Non dimensioni.
Brian R. Bondy,

11
Non se si chiama l'operatore new direttamente, quindi occorre il numero di byte da allocare come parametro.
Ferruccio,

1
Non sono sicuro, non ho mai sentito parlare di questa sintassi.
Brian R. Bondy,

9
L'opposto di operator newè operator delete. Non è un'azione ben definita chiamare deleteun'espressione con tipo void*.
CB Bailey,

33

Utilizzare malloce solo per allocare memoria che verrà gestita da librerie e API c-centric. Usa e (e le varianti) per tutto ciò che controlli.free newdelete[]


10
Nota anche che una libreria C ben scritta nasconderà malloc e libererà internamente, ecco come dovrebbe funzionare il programmatore C.
Dacav,

@dmckee hai un esempio di C ++ che usa le librerie c-centric di malloc e free?
Miglia,

1
@Dacav: se una funzione C accetterà un puntatore a un oggetto che dovrà continuare a utilizzare dopo il ritorno della funzione e il chiamante non avrà modo di sapere quando l'oggetto è ancora necessario, sarebbe perfettamente ragionevole per la funzione per specificare che il puntatore deve essere stato creato con malloc. Allo stesso modo se una funzione come strdupdeve creare un oggetto e restituirlo a un chiamante, è perfettamente ragionevole specificare che il chiamante deve chiamare freel'oggetto quando non è più necessario. In che modo tali funzioni potrebbero evitare di esporre il loro uso di malloc / free al chiamante?
supercat

@supercat, c'è qualcosa di intrinsecamente sbagliato nell'avere una funzione C che accetta un puntatore agli oggetti, poiché C non è affatto a conoscenza degli oggetti. In generale, credo che l'approccio migliore sia disporre di wrapper semantici attorno all'allocazione / deallocazione anche in C. Può essere ancora accettabile, ma meno flessibile, se una libreria C chiede al chiamante di pre-allocare e / o deallocare memoria. Se una funzione C sta eseguendo questa operazione e rivendica la proprietà sulla memoria allocata, viene implicitamente richiesto di allocarla con malloc.
Dacav,

@supercat Un esempio di un pacchetto di tutti i giorni che sono sicuro che tutti hanno usato è libgmp. Se hai mai usato una crittografia open source o un software basato su tale crittografia (il che è molto probabile), probabilmente hai usato una libreria aritmetica di precisione arbitraria che deve crescere e ridurre i propri dati interni. Questo viene fatto usando una funzione di inizializzazione ... e poi devi chiederti, come usi il codice C che è libgmp, in C ++, senza ricompilarlo in C ++? Ora con questo (il linker) in mente, pensaci ... perché mai una persona sensibile dovrebbe mai mettere mallocin C ++?
autistico,

31

new vs malloc ()

1) newè un operatore , mentre malloc()è una funzione .

2) newchiama costruttori , mentre malloc()non lo fa.

3) newrestituisce il tipo esatto di dati , mentre malloc()restituisce void * .

4) newnon restituisce mai un NULL (genererà un errore) mentre malloc()restituisce NULL

5) Riallocazione della memoria non gestita da newwhile malloc()can


6
Salve, per il punto 4), è possibile indicare a new di restituire NULL in caso di errore. char* ptr = new (std::nothrow) char [323232];
Singh,

1
6) new create da argomenti del costruttore, mentre malloc usa size.
Evan Moran,

c'è anche una newfunzione
Ma Ming,

Se tu fossi così incline in C da riallocare , spero che tu lo usi reallocpiuttosto che malloc, e inizi con la variabile del puntatore inizializzata su NULL. Se si desidera un pezzo di memoria ridimensionabile in C ++, d'altra parte, suggerirei std::vectoral contrario di realloc... Quello o un file.
autistico,

19

Per rispondere alla tua domanda, dovresti conoscere la differenza tra mallocenew . La differenza è semplice:

malloc alloca memoria , mentre new alloca memoria E chiama il costruttore dell'oggetto per cui stai allocando memoria.

Quindi, a meno che tu non sia limitato a C, non dovresti mai usare malloc, specialmente quando hai a che fare con oggetti C ++. Sarebbe una ricetta per interrompere il tuo programma.

Anche la differenza tra freee deleteè abbastanza la stessa. La differenza è che deletechiamerà il distruttore del tuo oggetto oltre a liberare memoria.


13

C'è una grande differenza tra malloce new. mallocalloca memoria. Questo va bene per C, perché in C un grumo di memoria è un oggetto.

In C ++, se non hai a che fare con tipi POD (che sono simili ai tipi C) devi chiamare un costruttore in una posizione di memoria per avere effettivamente un oggetto lì. I tipi non POD sono molto comuni in C ++, poiché molte funzionalità C ++ rendono automaticamente un oggetto non POD.

newalloca memoria e crea un oggetto su quella posizione di memoria. Per i tipi non POD questo significa chiamare un costruttore.

Se fai qualcosa del genere:

non_pod_type* p = (non_pod_type*) malloc(sizeof *p);

Il puntatore che ottieni non può essere dereferenziato perché non punta a un oggetto. Dovresti chiamare un costruttore su di esso prima di poterlo usare (e questo viene fatto usando il posizionamento new).

Se invece fai:

non_pod_type* p = new non_pod_type();

Ottieni un puntatore che è sempre valido, perché ha newcreato un oggetto.

Anche per i tipi POD, c'è una differenza significativa tra i due:

pod_type* p = (pod_type*) malloc(sizeof *p);
std::cout << p->foo;

Questo pezzo di codice stamperebbe un valore non specificato, poiché gli oggetti POD creati da mallocnon vengono inizializzati.

Con new, è possibile specificare un costruttore da chiamare e quindi ottenere un valore ben definito.

pod_type* p = new pod_type();
std::cout << p->foo; // prints 0

Se lo vuoi davvero, puoi usare use newper ottenere oggetti POD non inizializzati. Vedi questa altra risposta per ulteriori informazioni al riguardo.

Un'altra differenza è il comportamento in caso di fallimento. Quando non riesce a allocare memoria, mallocrestituisce un puntatore null, mentre newgenera un'eccezione.

Il primo richiede di testare ogni puntatore restituito prima di utilizzarlo, mentre il successivo produrrà sempre puntatori validi.

Per questi motivi, nel codice C ++ è necessario utilizzare newe non malloc. Ma anche allora, non dovresti usare new"all'aperto", perché acquisisce risorse che devi rilasciare in seguito. Quando lo usi new, dovresti passare immediatamente il risultato in una classe di gestione delle risorse:

std::unique_ptr<T> p = std::unique_ptr<T>(new T()); // this won't leak

7

L'allocazione dinamica è richiesta solo quando il tempo di vita dell'oggetto deve essere diverso dall'ambito in cui viene creato (vale anche per rendere l'ambito più piccolo più grande) e hai un motivo specifico in cui non è memorizzato per valore lavoro.

Per esempio:

 std::vector<int> *createVector(); // Bad
 std::vector<int> createVector();  // Good

 auto v = new std::vector<int>(); // Bad
 auto result = calculate(/*optional output = */ v);
 auto v = std::vector<int>(); // Good
 auto result = calculate(/*optional output = */ &v);

Da C ++ 11 in poi, abbiamo std::unique_ptra che fare con la memoria allocata, che contiene la proprietà della memoria allocata. std::shared_ptrè stato creato per quando devi condividere la proprietà. (ti servirà meno di quanto ti aspetteresti in un buon programma)

La creazione di un'istanza diventa davvero semplice:

auto instance = std::make_unique<Class>(/*args*/); // C++14
auto instance = std::make_unique<Class>(new Class(/*args*/)); // C++11
auto instance = std::make_unique<Class[]>(42); // C++14
auto instance = std::make_unique<Class[]>(new Class[](42)); // C++11

C ++ 17 aggiunge anche std::optionalche può impedire di richiedere allocazioni di memoria

auto optInstance = std::optional<Class>{};
if (condition)
    optInstance = Class{};

Non appena "istanza" esce dall'ambito, la memoria viene ripulita. Il trasferimento della proprietà è anche facile:

 auto vector = std::vector<std::unique_ptr<Interface>>{};
 auto instance = std::make_unique<Class>();
 vector.push_back(std::move(instance)); // std::move -> transfer (most of the time)

Quindi quando hai ancora bisogno new? Quasi mai da C ++ 11 in poi. La maggior parte di essi viene utilizzata std::make_uniquefino a quando non si raggiunge un punto in cui si colpisce un'API che trasferisce la proprietà tramite puntatori non elaborati.

 auto instance = std::make_unique<Class>();
 legacyFunction(instance.release()); // Ownership being transferred

 auto instance = std::unique_ptr<Class>{legacyFunction()}; // Ownership being captured in unique_ptr

In C ++ 98/03, è necessario eseguire la gestione manuale della memoria. In questo caso, prova a passare a una versione più recente dello standard. Se sei bloccato:

 auto instance = new Class(); // Allocate memory
 delete instance;             // Deallocate
 auto instances = new Class[42](); // Allocate memory
 delete[] instances;               // Deallocate

Assicurati di monitorare correttamente la proprietà per non avere perdite di memoria! La semantica di Move non funziona ancora.

Quindi, quando avremo bisogno di malloc in C ++? L'unico motivo valido sarebbe quello di allocare memoria e inizializzarla in seguito tramite il posizionamento nuovo.

 auto instanceBlob = std::malloc(sizeof(Class)); // Allocate memory
 auto instance = new(instanceBlob)Class{}; // Initialize via constructor
 instance.~Class(); // Destroy via destructor
 std::free(instanceBlob); // Deallocate the memory

Anche se quanto sopra è valido, questo può essere fatto anche tramite un nuovo operatore. std::vectorè un buon esempio per questo.

Infine, abbiamo ancora l'elefante nella stanza: C. Se devi lavorare con una libreria C in cui la memoria viene allocata nel codice C ++ e liberata nel codice C (o viceversa), sei costretto a usare malloc / free.

Se ti trovi in ​​questo caso, dimentica le funzioni virtuali, le funzioni membro, le classi ... Sono consentite solo le strutture con POD.

Alcune eccezioni alle regole:

  • Stai scrivendo una libreria standard con strutture dati avanzate in cui malloc è appropriato
  • Devi allocare grandi quantità di memoria (nella copia di memoria di un file da 10 GB?)
  • Hai degli strumenti che ti impediscono di usare determinati costrutti
  • Devi memorizzare un tipo incompleto

6

Ci sono alcune cose che newnon lo mallocfanno:

  1. new costruisce l'oggetto chiamando il costruttore di quell'oggetto
  2. new non richiede il typecasting della memoria allocata.
  3. Non richiede l'allocazione di una quantità di memoria, ma richiede la creazione di un numero di oggetti.

Quindi, se usi malloc, allora devi fare esplicitamente le cose sopra, il che non è sempre pratico. Inoltre, newpuò essere sovraccarico ma mallocnon può esserlo.


5

Se lavori con dati che non richiedono costruzione / distruzione e richiedono riallocazioni (ad es. Una vasta gamma di ints), credo che malloc / free sia una buona scelta in quanto ti dà realloc, che è molto più veloce di new-memcpy -delete (è sulla mia scatola di Linux, ma suppongo che questo possa dipendere dalla piattaforma). Se si lavora con oggetti C ++ che non sono POD e richiedono costruzione / distruzione, è necessario utilizzare gli operatori new ed delete.

Ad ogni modo, non vedo perché non dovresti usare entrambi (purché tu liberi la memoria malloced ed elimini gli oggetti allocati con nuovi) se puoi trarre vantaggio dall'aumento di velocità (a volte significativo, se stai reallando grandi array di POD) che realloc può darti.

A meno che non sia necessario, è necessario attenersi a new / delete in C ++.


3

Se si dispone del codice C che si desidera trasferire su C ++, è possibile lasciare qualsiasi chiamata malloc (). Per qualsiasi nuovo codice C ++, consiglierei invece di usare new.


3

Se stai usando C ++, prova a usare new / delete invece di malloc / calloc in quanto sono operatori. Per malloc / calloc, è necessario includere un'altra intestazione. Non mescolare due lingue diverse nello stesso codice. Il loro lavoro è simile in ogni modo, entrambi alloca la memoria in modo dinamico dal segmento heap nella tabella hash.


2

new inizializzerà i valori predefiniti di struct e collegherà correttamente i riferimenti in esso a se stesso.

Per esempio

struct test_s {
    int some_strange_name = 1;
    int &easy = some_strange_name;
}

Quindi new struct test_srestituirà una struttura inizializzata con un riferimento funzionante, mentre la versione malloc non ha valori predefiniti e i riferimenti interni non sono inizializzati.


1

Da una prospettiva inferiore, new inizializzerà tutta la memoria prima di dare memoria, mentre malloc manterrà il contenuto originale della memoria.


4
new non inizializza in generale la memoria, anche se ci sono modi per farlo accadere: vedi stackoverflow.com/questions/2204176/… per una discussione al riguardo.
wjl,

0

Nel seguente scenario, non possiamo usare new poiché chiama il costruttore.

class  B  {
private:
    B *ptr;
    int x;
public:
    B(int n)  {
        cout<<"B: ctr"<<endl;
        //ptr = new B;  //keep calling ctr, result is segmentation fault
        ptr = (B *)malloc(sizeof(B));
        x = n;
        ptr->x = n + 10;
    }
    ~B()  {
        //delete ptr;
        free(ptr);
        cout<<"B: dtr"<<endl;
    }
};

0

Gli operatori newe deletepossono operare su classi e strutture, mentre malloce freefunzionano solo con blocchi di memoria che devono essere espressi.

L'utilizzo new/deleteaiuterà a migliorare il codice in quanto non sarà necessario trasmettere la memoria allocata alla struttura di dati richiesta.


0

Caso raro da considerare l'utilizzo di malloc / free anziché new / delete è quando si allocano e quindi si riallocano (tipi di pod semplici, non oggetti) usando realloc in quanto non esiste una funzione simile a realloc in C ++ (sebbene ciò possa essere fatto usando un più approccio C ++).


-4

malloc () è usato per assegnare dinamicamente la memoria in C mentre lo stesso lavoro è fatto da new () in c ++. Quindi non è possibile combinare convenzioni di codifica in 2 lingue. Sarebbe bello se tu chiedessi la differenza tra calloc e malloc ()


2
È possibile (ma quasi sempre non dovrebbe) utilizzare mallocin C ++.
interjay,

1
Hai anche perso il punto principale che dovresti mirare a evitare l'allocazione dinamica della memoria, a meno che non lo fai tramite i puntatori intelligenti. Ti stai solo preparando per il dolore, altri saggi
diavolo
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.