Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
In tegenstelling tot beheerde talen beschikt C++ niet over automatische garbagecollection, een intern proces dat heapgeheugen en andere resources vrijgeeft als een programma wordt uitgevoerd. Een C++-programma is verantwoordelijk voor het retourneren van alle verkregen resources naar het besturingssysteem. Een niet-vrijgegeven ongebruikte resource wordt een lek genoemd. Gelekte resources zijn niet beschikbaar voor andere programma's totdat het proces wordt afgesloten. Geheugenlekken zijn met name een veelvoorkomende oorzaak van bugs in het programmeren in C-stijl.
Moderne C++ vermijdt het gebruik van heap-geheugen zoveel mogelijk door objecten op de stack te declareren. Wanneer een resource te groot is voor de stack, moet deze eigendom zijn van een object. Wanneer het object wordt geïnitialiseerd, verkrijgt het de resource die het toebehoort. Het object is vervolgens verantwoordelijk voor het vrijgeven van de resource in de destructor. Het eigenaar-object wordt op de stapel gedeclareerd. Het principe dat objecten eigenaar zijn van resources, staat ook wel bekend als "resourceverwerving is initialisatie" of RAII.
Wanneer een stackobject dat eigenaar is van een resource buiten het bereik valt, wordt de destructor automatisch aangeroepen. Op deze manier hangt garbage collection in C++ nauw samen met de levensduur van objecten en is het deterministisch. Een resource wordt altijd vrijgegeven op een bekend punt in het programma, dat u kunt beheren. Alleen deterministische destructors zoals die in C++ kunnen geheugen- en niet-geheugenbronnen even goed verwerken.
In het volgende voorbeeld ziet u een eenvoudig object w
. Deze wordt gedeclareerd op de stack op functieniveau en wordt aan het einde van het functieblok vernietigd. Het object w
is eigenaar van geen resources (zoals heap-toegewezen geheugen). Het enige lid g
is zelf gedeclareerd op de stack en gaat gewoon buiten het bereik met w
. Er is geen speciale code nodig in de widget
destructor.
class widget {
private:
gadget g; // lifetime automatically tied to enclosing object
public:
void draw();
};
void functionUsingWidget () {
widget w; // lifetime automatically tied to enclosing scope
// constructs w, including the w.g gadget member
// ...
w.draw();
// ...
} // automatic destruction and deallocation for w and w.g
// automatic exception safety,
// as if "finally { w.dispose(); w.g.dispose(); }"
In het volgende voorbeeld is w
de eigenaar van een geheugenresource en moet er dus code in zijn destructor zijn om het geheugen te verwijderen.
class widget
{
private:
int* data;
public:
widget(const int size) { data = new int[size]; } // acquire
~widget() { delete[] data; } // release
void do_something() {}
};
void functionUsingWidget() {
widget w(1000000); // lifetime automatically tied to enclosing scope
// constructs w, including the w.data member
w.do_something();
} // automatic destruction and deallocation for w and w.data
Omdat C++11 is er een betere manier om het vorige voorbeeld te schrijven: met behulp van een slimme aanwijzer uit de standaardbibliotheek. De smart pointer beheert de toewijzing en verwijdering van het geheugen dat het bezit. Het gebruik van een slimme aanwijzer elimineert de noodzaak van een expliciete destructor in de widget
klasse.
#include <memory>
class widget
{
private:
std::unique_ptr<int[]> data;
public:
widget(const int size) { data = std::make_unique<int[]>(size); }
void do_something() {}
};
void functionUsingWidget() {
widget w(1000000); // lifetime automatically tied to enclosing scope
// constructs w, including the w.data gadget member
// ...
w.do_something();
// ...
} // automatic destruction and deallocation for w and w.data
Door slimme aanwijzers te gebruiken voor geheugentoewijzing, kunt u het potentieel voor geheugenlekken elimineren. Dit model werkt voor andere resources, zoals bestandshandvatten of sockets. U kunt uw eigen resources op een vergelijkbare manier beheren in uw klassen. Zie Slimme aanwijzers voor meer informatie.
Het ontwerp van C++ zorgt ervoor dat objecten worden vernietigd wanneer ze buiten het bereik vallen. Dat wil zeggen, ze worden vernietigd als blokken worden afgesloten, in omgekeerde volgorde van opbouw. Wanneer een object wordt vernietigd, worden zijn basisen en leden in een bepaalde volgorde vernietigd. Objecten die buiten een blok in de globale scope zijn gedeclareerd, kunnen leiden tot problemen. Het kan lastig zijn om fouten op te sporen als de constructor van een globaal object een uitzondering genereert.
Zie ook
Welkom terug in C++
Naslaginformatie over C++-taal
C++ Standaardbibliotheek