ProgrammatieC++ ontwikkelaar, systeem programmeur

Vertel over het mechanisme operator new/operator delete in C++. Hoe verschillen ze van new/delete en wanneer en waarom worden operatorfuncties overschreven in gebruikersklassen?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord.

In C++ zijn operator new en operator delete functies voor het toewijzen en vrijgeven van geheugen die worden aangeroepen bij het plaatsen en verwijderen van objecten via de operators new en delete. Standaard gebruiken ze de standaard allocator, maar in een klas kunnen ze worden overloaded voor een fijne controle over geheugenallocatie.

  • operator new wijst een "ruw" stuk geheugen toe zonder de constructor aan te roepen.
  • Na het toewijzen van geheugen wordt automatisch de constructor van het object aangeroepen.
  • operator delete geeft geheugen vrij na het voltooien van de destructor van het object.

Gebruik (globale en lokale versies):

  • De globale versie wordt standaard toegepast (bijvoorbeeld, bij new int).
  • Door een specifieke operator new in een klas te overschrijven, kan de werking met geheugen voor objecten van deze klas worden geoptimaliseerd (bijvoorbeeld, objectpool, tracering, hergebruik van blokken).

Voorbeeld van het overschrijven van operator new/operator delete:

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

Fijnere details:

  • Het aanroepen van nieuwe/verwijdering van objecten met argumenten (placement new) vereist een aparte overload.
  • Overschreven operators worden alleen aangeroepen bij het maken/verwijderen van objecten van die klas en niet voor new[]/delete[]. Voor hen kunnen aparte operator new[]/delete[] worden overloaded.
  • Geheugenmanipulatie is gevaarlijk — correcte exception handling is vereist.

Vraag met een valstrik.

"Wat gebeurt er als je operator new in een klas overlaadt en vervolgens een object via een geerfd klassenaam maakt? Welke versie van operator new wordt aangeroepen?"

Antwoord: De operator new van de klasse waarvan het object wordt aangemaakt, zal worden aangeroepen. Als de afgeleide klasse geen operator new heeft geïmplementeerd, zal er een poging worden gedaan om de juiste versie in de basisklasse of de globale versie te vinden.

Voorbeeld:

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

Voorbeelden van echte fouten door onwetendheid over deze details.


Geschiedenis

Ontwikkelaars overloadeden operator new/ delete zonder zorg voor correcte exception handling. Bij het gooien van een uitzondering binnen de constructor werd het geheugen niet vrijgegeven, wat leidde tot geheugenlekken.


Geschiedenis

Incorrecte implementatie van operator new[] en operator delete[]: voor een klas binnen welke arrays werden vastgehouden, werd de nieuwe implementatie niet aangeroepen — de standaardversies werden gebruikt, wat leidde tot een desynchronisatie van de logica achter het toewijzen en vrijgeven van geheugen.


Geschiedenis

Het overroepen van de globale operator new beïnvloedde de werking van externe bibliotheken: alle objecten (inclusief tijdelijke en uit STL) begonnen te worden gealloceerd via de gelogde allocator, wat de werking van de applicatiekern significant vertraagde.