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.