ProgrammierungC++ Entwickler, Systemprogrammierer

Erzählen Sie von den Mechanismen operator new/operator delete in C++. Wie unterscheiden sie sich von new/delete, wann und warum werden Operatorfunktionen in benutzerdefinierten Klassen überschrieben?

Bestehen Sie Vorstellungsgespräche mit dem Hintsage-KI-Assistenten

Antwort.

In C++ sind operator new und operator delete Funktionen zur Speicherzuweisung und -freigabe, die beim Platzieren und Löschen von Objekten über die Operatoren new und delete aufgerufen werden. Standardmäßig verwenden sie den standardmäßigen Allocator, aber in der Klasse können sie überschrieben werden, um eine feine Kontrolle über die Speicherzuweisung zu haben.

  • operator new weist einen "rohen" Speicherbereich zu, ohne den Konstruktor aufzurufen.
  • Nach der Speicherzuweisung wird automatisch der Konstruktor des Objekts aufgerufen.
  • operator delete gibt den Speicher frei, nachdem der Destruktor des Objekts abgeschlossen ist.

Verwendung (globale und lokale Versionen):

  • Die globale Version wird standardmäßig verwendet (z. B. bei new int).
  • Durch Überschreiben des spezifischen operator new in der Klasse können Sie die Speicherverwaltung für Objekte dieser Klasse optimieren (z. B. Objektpool, Tracierung, Wiederverwendung von Blöcken).

Beispiel für die Überladung von operator new/operator delete:

#include <iostream> class TrackAlloc { public: void* operator new(size_t size) { std::cout << "TrackAlloc::new für " << size << " bytes "; return ::operator new(size); } void operator delete(void* ptr) { std::cout << "TrackAlloc::delete "; ::operator delete(ptr); } };

Feinheiten:

  • Der Aufruf neuer/Löschobjekte mit Argumenten (placement new) erfordert eine separate Überladung.
  • Überschriebene Operatoren werden nur beim Erstellen/Löschen von Objekten der Klasse aufgerufen, nicht für new[]/delete[]. Für diese können separate operator new[]/delete[] überladen werden.
  • Speicher-Manipulationen sind gefährlich — eine korrekte Ausnahmebehandlung ist erforderlich.

Fangfrage.

"Was passiert, wenn der Operator new in einer Klasse überschrieben wird und dann ein Objekt über eine Variable der abgeleiteten Klasse erstellt wird? Welche Version von operator new wird aufgerufen?"

Antwort: Es wird der operator new der Klasse aufgerufen, von der das Objekt erstellt wird. Wenn der abgeleitete Klasse kein operator new implementiert hat, wird versucht, die geeignete Version in der Basis- oder globalen Version zu finden.

Beispiel:

struct Base { void* operator new(size_t s) { std::cout << "Base new "; return ::operator new(s); } }; struct Derived : Base {}; Derived* p = new Derived; // Ruft Base::operator new auf!

Beispiele für reale Fehler aufgrund fehlenden Wissens über die Feinheiten des Themas.


Geschichte

Entwickler haben operator new/delete ohne Unterstützung einer korrekten Ausnahmebehandlung überladen. Bei einer Ausnahme im Konstruktor wurde der Speicher nicht freigegeben, was zu Lecks führte.


Geschichte

operator new[] und operator delete[] wurden fehlerhaft implementiert: Für Klassen, die Arrays enthalten, wurde die neue Implementierung nicht aufgerufen — es wurden die Standardversionen verwendet, was zu einer Desynchronisierung der Logik der Speicherzuweisung und -freigabe führte.


Geschichte

Die Überschreibung der globalen operator new beeinflusste die Funktion anderer Bibliotheken: Alle Objekte (auch temporäre und aus STL) wurden über den protokollierenden Allocator zugewiesen, was die Leistung des Anwendungskerns erheblich verlangsamte.