Frage

Dies ist eine Frage, die mich seit einiger Zeit quälende worden ist. Ich habe immer gedacht, dass C ++ entwickelt wurde, sollte, so dass der „Löschen“ Operator (ohne Klammern) funktioniert auch mit dem „neuen []“ Operator.

Meiner Meinung nach, schreibe dies:

int* p = new int;

sollte einen Array von 1 Elemente Zuteilen äquivalent sein:

int* p = new int[1];

Wenn dies wahr ist, das "Löschen" Operator immer Arrays sein könnte löschen, und wir würden den "delete []" Operator nicht benötigen.

Gibt es einen Grund, warum die "delete []" Operator in C ++ eingeführt wurde? Der einzige Grund, warum ich denken kann, ist, dass Arrays Zuweisen einen geringen Speicherbedarf hat (Sie die Größe des Array irgendwo zu speichern haben), so dass die Unterscheidung „löscht“ vs „delete []“ war eine kleine Speicheroptimierung.

War es hilfreich?

Lösung

Es ist so, dass die Destruktoren der einzelnen Elemente genannt werden. Ja, für Arrays von PODs, gibt es einen Unterschied nicht viel, aber in C ++, können Sie Arrays von Objekten mit nicht-trivialen Destruktoren haben.

Nun, Ihre Frage ist, warum nicht new machen und delete wie new[] und delete[] verhalten und los new[] und delete[] bekommen? Ich würde wieder Stroustrup „Design and Evolution“ Buch, in dem er sagte, dass, wenn Sie C ++ keine Funktionen verwenden, sollten Sie nicht für sie bezahlen müssen (zur Laufzeit zumindest). So wie es jetzt steht, ein new oder delete wird so effizient wie malloc und free verhalten. Wenn delete den delete[] Sinn hatte, gäbe es einigen zusätzlichen Aufwand zur Laufzeit (wie James Curran darauf hingewiesen).

Andere Tipps

Verdammt, vermisste ich den ganzen Sinn der Frage, aber ich werde meine ursprüngliche Antwort als Nebenbei bemerkt verlassen. Warum wir löschen müssen [] ist, weil schon vor langer Zeit wir löschen hatte [cnt], auch heute noch, wenn Sie löschen schreiben [9] oder löschen [cnt], der Compiler ignoriert einfach die Sache zwischen [] sondern kompiliert ok. Zu dieser Zeit wurde C ++ zuerst von einem Front-End verarbeitet und dann auf einen gewöhnlichen C-Compiler zugeführt. Sie konnten nicht den Trick von den Grafen irgendwo unter dem Vorhang zu speichern, vielleicht könnten sie nicht einmal daran zu denken, zu diesem Zeitpunkt. Und für die Abwärtskompatibilität, der Compiler höchstwahrscheinlich den Wert zwischen dem [] als Anzahl der Array gegeben verwendet, wenn kein solcher Wert ist dann bekam sie die Zählung aus dem Präfix, so arbeitete es in beiden Richtungen. Später, typisiert wir nichts zwischen [] und alles funktionierte. Heute glaube ich nicht „delete []“ ist notwendig, aber die Implementierungen verlangen es so.

Meine ursprüngliche Antwort (die den Punkt verfehlt) ::

„Löschen“ löscht ein einzelnes Objekt. "Delete []" löscht ein Objekt-Array. Für delete [] arbeiten, hält die Umsetzung der Anzahl der Elemente im Array. Ich habe doppelt geprüft dies durch ASM-Code debuggen. Bei der Umsetzung (VS2005) I getestet wurde die Zählung als Präfix zu dem Objekt-Array gespeichert.

Wenn Sie „delete []“ verwenden, um auf ein einzelnes Objekt, die Zählvariable ist Müll so den Code stürzt ab. Wenn Sie „Löschen“ für ein Objekt-Array verwenden, weil einige Inkonsistenzen, stürzt der Code. Getestet habe ich diese Fälle gerade jetzt!

„Löschen löscht nur den Speicher für das Array zugeordnet.“ Anweisung in einer anderen Antwort ist nicht richtig. Wenn das Objekt eine Klasse ist, löschen Sie den DTOR rufen. Legen Sie einfach einen Haltepunkt int der DTOR Code und löschen Sie das Objekt, wird der Haltepunkt erreicht.

Was fiel mir ein, dass, wenn der Compiler & Bibliotheken angenommen, dass alle Objekte, die von „neu“ sind Objekt-Arrays zugeordnet, wäre es in Ordnung sein „löschen“ Arrays für einzelne Objekte oder Objekt aufzurufen. Einzelne Objekte würde nur der Sonderfall eines Objekts Array eine Zählung von 1. Vielleicht ist etwas, mir fehlt, sowieso ...

Da alle anderen scheint der Punkt Ihrer Frage verpasst zu haben, werde ich nur hinzufügen, dass ich den gleichen Gedanken hatte einige Jahre her, und nie in der Lage gewesen, eine Antwort zu bekommen.

Das einzige, was ich denken kann, ist, dass ein sehr kleines bisschen zusätzlichen Overhead gibt es ein einzelnes Objekt als ein Array (eine unnötige „for(int i=0; i<1; ++i)“)

zur Behandlung von

Addiert man diese, da keine andere Antwort zur Zeit richtet sie an:

Array delete[] kann nicht auf einem Zeiger-to-Basisklasse jemals verwendet werden - während der Compiler speichert die Anzahl der Objekte, wenn Sie new[] aufrufen, ist es nicht die Typen oder Größen der Objekte speichert (wie David wies darauf hin, in C ++ zahlen Sie nur selten für eine Funktion sind Sie nicht verwenden). Allerdings kann Skalar delete sicher durch Basisklasse löschen, so ist es sowohl für die normale Objekt Bereinigung und polymorphe Bereinigung verwendet:

struct Base { virtual ~Base(); };
struct Derived : Base { };
int main(){
    Base* b = new Derived;
    delete b; // this is good

    Base* b = new Derived[2];
    delete[] b; // bad! undefined behavior
}

jedoch im entgegengesetzten Fall - nicht-virtuelle Destruktor - Skalar delete sollte so billig wie möglich sein - es sollte für die Anzahl der Objekte nicht überprüfen, noch für die Art des Objekts gelöscht werden. Dies macht auf ein integrierter Typ oder plain-old-Datentyp sehr billig löschen, wie der Compiler nur ::operator delete und nichts aufrufen muss anders:

int main(){
    int * p = new int;
    delete p; // cheap operation, no dynamic dispatch, no conditional branching
}

Während keine erschöpfende Behandlung von Speicherzuweisung, ich hoffe das die Breite der Speichermanagementoptionen in C hilft klären ++.

Marshall Cline hat einige Informationen zu diesem Thema .

delete [] stellt sicher, daß der Destruktor jedes Mitglied (gegebenenfalls nach Art) aufgerufen wird, während delete nur den Speicher für das Array zugeordnet löscht.

Hier ist gut zu lesen: http: //www.informit. com / guides / content.aspx? g = cplusplus & SEQNUM = 287

Und nein, Feldgrößen sind nicht überall in C ++ gespeichert. (Danke an alle für den Hinweis auf, dass diese Aussage ungenau ist.)

Ich bin ein bisschen von Aaron Antwort verwirrt und offen zugeben, dass ich nicht ganz verstehen, warum und wo löschen [] benötigt wird.

ich einige Experimente mit dem Beispielcode hat (nach ein paar Tippfehler Fixierung). Hier sind meine Ergebnisse.     Typos: ~ benötigte Basis einen Funktionskörper     Basis * b wurde zweimal erklärt

struct Base { virtual ~Base(){ }>; };
struct Derived : Base { };
int main(){
Base* b = new Derived;
delete b; // this is good

<strike>Base</strike> b = new Derived[2];
delete[] b; // bad! undefined behavior
}

Kompilierung und Ausführung

david@Godel:g++ -o atest atest.cpp 
david@Godel: ./atest 
david@Godel: # No error message

Modifizierte Programm mit delete [] entfernt

struct Base { virtual ~Base(){}; };
struct Derived : Base { };

int main(){
    Base* b = new Derived;
    delete b; // this is good

    b = new Derived[2];
    delete b; // bad! undefined behavior
}

Kompilierung und Ausführung

david@Godel:g++ -o atest atest.cpp 
david@Godel: ./atest 
atest(30746) malloc: *** error for object 0x1099008c8: pointer being freed was n
ot allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6

Natürlich, ich weiß nicht, ob löscht [] b ist im ersten Beispiel tatsächlich arbeiten; Ich weiß, dass es nicht nur eine Compiler-Fehlermeldung nicht geben.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top