delete vs delete [] operatori in C ++


136

Qual è la differenza tra deletee delete[]operatori in C ++?


Si potrebbe trovare questa questione rilevante stackoverflow.com/questions/1913343/...
sharptooth

7
I problemi con delete ed delete [] sono uno dei motivi per cui mi piacciono i puntatori intelligenti e l'utilizzo vector<>invece di un array ogni volta che posso.
David Thornley,


@DavidThornley Se si utilizzano i puntatori intelligenti, è comunque necessario conoscere la differenza nel senso che è ancora necessario sapere di non scrivere std::unique_ptr<int>(new int[3]), ad es . Perché chiamerà regolarmente deletesull'array che è un comportamento indefinito. Invece devi usarestd::unique_ptr<int[]>
Arthur Tacca

Risposte:


151

L' deleteoperatore disloca la memoria e chiama il distruttore per un singolo oggetto creato con new.

L' delete []operatore disloca la memoria e chiama i distruttori per una matrice di oggetti creati con new [].

L'utilizzo deletesu un puntatore restituito da new []o delete []su un puntatore restituito da newcomporta un comportamento indefinito.


3
Mi chiedo se l'uso di delete su un nuovo array [] di tipi primitivi come int o char (nessun costruttore / distruttore) porti necessariamente anche a comportamenti indefiniti. Sembra che la dimensione dell'array non sia memorizzata da nessuna parte quando si usano tipi primitivi.
thomiel,

21
Se lo standard non definisce cosa succede quando ciò viene fatto, è per definizione "comportamento indefinito", anche se il compilatore fa in modo deterministico quello che vorresti che facesse. Un altro compilatore può fare qualcosa di completamente diverso.
Rob K,

Ho fatto questo errore quando avevo una matrice di stringhe C come "char ** strArray". Se hai un array come me, devi scorrere l'array ed eliminare / liberare ogni elemento, quindi eliminare / liberare lo strArray stesso. L'uso di "delete []" sull'array che ho non funziona dal momento che (come sottolineato dai commenti e dalla risposta sopra), CHIAMA DISTRUTTORI, in realtà non libera ogni slot.
Katianie,

88

L' delete[]operatore viene utilizzato per eliminare le matrici. L' deleteoperatore viene utilizzato per eliminare oggetti non array. Richiama operator delete[]e operator deletefunziona rispettivamente per eliminare la memoria occupata dall'array o dall'oggetto non array dopo (eventualmente) chiamare i distruttori per gli elementi dell'array o l'oggetto non array.

Quanto segue mostra le relazioni:

typedef int array_type[1];

// create and destroy a int[1]
array_type *a = new array_type;
delete [] a;

// create and destroy an int
int *b = new int;
delete b;

// create and destroy an int[1]
int *c = new int[1];
delete[] c;

// create and destroy an int[1][2]
int (*d)[2] = new int[1][2];
delete [] d;

Per newquesto crea un array (quindi, new type[]o newapplicato a un costrutto di tipo array), lo Standard cerca un operator new[]nella classe del tipo di elemento dell'array o nell'ambito globale e passa la quantità di memoria richiesta. Potrebbe richiedere più di N * sizeof(ElementType)quanto desideri (ad esempio per memorizzare il numero di elementi, quindi in seguito, quando si elimina, sa quante chiamate del distruttore devono essere eseguite). Se la classe dichiara operator new[]un'aggiunta alla quantità di memoria accetta un'altra size_t, quel secondo parametro riceverà il numero di elementi allocati - può usarlo per qualsiasi scopo (debug, ecc ...).

Per quello newche crea un oggetto non-array, cercherà un operator newnella classe dell'elemento o nell'ambito globale. Passa la quantità di memoria richiesta (esattamente sizeof(T)sempre).

Per il delete[], esamina il tipo di classe di elementi delle matrici e chiama i loro distruttori. La operator delete[]funzione utilizzata è quella nella classe del tipo di elemento, o se non ce n'è nessuna nell'ambito globale.

Infatti delete, se il puntatore passato è una classe base del tipo di oggetto reale, la classe base deve avere un distruttore virtuale (altrimenti il ​​comportamento non è definito). Se non è una classe base, viene chiamato il distruttore di quella classe e viene usato un operator deletein quella classe o il globale operator delete. Se è stata passata una classe di base, viene chiamato il distruttore del tipo di oggetto reale e operator deleteviene utilizzato il trovato in quella classe, o se non ce n'è nessuno, operator deleteviene chiamato un globale . Se operator deletenella classe ha un secondo parametro di tipo size_t, riceverà il numero di elementi da deallocare.


18

Questo è l'uso base del modello allocate / DE-allocate in c ++ malloc/ free, new/ delete, new[]/delete[]

Dobbiamo usarli di conseguenza. Ma vorrei aggiungere questa particolare comprensione per la differenza tra deleteedelete[]

1) deleteviene utilizzato per disallocare la memoria allocata per singolo oggetto

2) delete[]viene utilizzato per disallocare la memoria allocata per la matrice di oggetti

class ABC{}

ABC *ptr = new ABC[100]

quando diciamo new ABC[100], il compilatore può ottenere le informazioni su quanti oggetti deve essere allocato (qui è 100) e chiamerà il costruttore per ciascuno degli oggetti creati

ma di conseguenza, se usiamo semplicemente delete ptrquesto caso, il compilatore non saprà quanti oggetti ptrpunta e finirà per chiamare il distruttore e cancellare la memoria per 1 solo oggetto (lasciando l'invocazione dei distruttori e la deallocazione dei rimanenti 99 oggetti). Quindi ci sarà una perdita di memoria.

quindi dobbiamo usare delete [] ptrin questo caso.


3
Questa dovrebbe essere la risposta corretta. Nessuna delle altre risposte menziona la netta differenza: "ma di conseguenza se utilizziamo semplicemente elimina ptr per questo caso, il compilatore non saprà a quanti oggetti punta ptr e finirà per chiamare il distruttore e cancellare la memoria per un solo oggetto"
Don Larynx,

1
Come possiamo ottenere la stessa cosa in C?
Dogus Ural,

@DogusUral Perché? Non ci sono distruttori in C, quindi solo free()questo e quello. Se usi un modello pseudo-distruttore, devi chiamarlo una volta per ogni oggetto usando un forciclo.
Kotauskas,

@DonLarynx la differenza corretta è che mescolarli si traduce in un programma mal formato. Un'implementazione potrebbe sapere quanti oggetti distruggere o no . È consentito sapere che è stato chiamato in modo errato e interrompere il programma indicando dove si trova il problema.
Caleth,

6

Gli operatori deletee delete []vengono utilizzati rispettivamente per distruggere gli oggetti creati con newe new[], tornando alla memoria allocata lasciata disponibile al gestore della memoria del compilatore.

Gli oggetti creati con newdevono necessariamente essere distrutti deletee con cui gli array creati new[]devono essere eliminati delete[].


2

Quando ho posto questa domanda, la mia vera domanda era: "c'è una differenza tra i due? Il runtime non deve conservare le informazioni sulla dimensione dell'array, e quindi non sarà in grado di dire quale intendiamo?" Questa domanda non appare nelle "domande correlate", quindi solo per dare una mano a quelli come me, ecco la risposta: "perché abbiamo persino bisogno dell'operatore delete []?"


Grazie per essere tornato e
averlo inserito

0

deleteviene utilizzato per un singolo puntatore e delete[]viene utilizzato per eliminare un array tramite un puntatore. Questo potrebbe aiutarti a capire meglio.


-6

Beh .. forse penso che sia solo per esplicito. L'operatore deletee l'operatore delete[]si distinguono ma anche l' deleteoperatore può rilasciare l'array.

test* a = new test[100];
delete a;

E già verificato che questo codice non abbia perdite di memoria.

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.