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.
operators voor
C++ ondersteunt dynamische toewijzing en deallocatie van objecten met behulp van de new en delete operators. Deze operators wijzen geheugen toe voor objecten uit een pool die de gratis opslag wordt genoemd (ook wel bekend als de heap). De new operator roept de speciale functie operator newaan en de delete operator roept de speciale functie operator deleteaan.
Zie crt-bibliotheekfuncties voor een lijst met bibliotheekbestanden in de C Runtime-bibliotheek en de C++-standaardbibliotheek.
De new operator
De compiler vertaalt een instructie zoals deze in een aanroep naar de functie operator new:
char *pch = new char[BUFFER_SIZE];
Als de aanvraag voor nul bytes aan opslag is, operator new retourneert u een aanwijzer naar een afzonderlijk object. Dat wil gezegd, herhaalde aanroepen om operator new verschillende aanwijzers te retourneren.
Als er onvoldoende geheugen is voor de toewijzingsaanvraag, operator new genereert u een std::bad_alloc uitzondering. Of het retourneert als u het plaatsingsformuliernew(std::nothrow)nullptr hebt gebruikt of als u hebt gekoppeld aan niet-gooiende operator new ondersteuning. Zie Gedrag van toewijzingsfouten voor meer informatie.
De twee bereiken voor operator new functies worden beschreven in de volgende tabel.
Bereik voor operator new functies
| Operateur | Omvang |
|---|---|
::operator new |
Globaal |
klassenaam::operator new |
Klasse |
Het eerste argument van operator new het type moet van het type size_tzijn en het retourtype is altijd void*.
De globale operator new functie wordt aangeroepen wanneer de operator wordt gebruikt voor het toewijzen van objecten van ingebouwde typen, objecten van klassetype die geen door de new gebruiker gedefinieerde operator new functies en matrices van elk type bevatten. Wanneer de operator wordt gebruikt voor het new toewijzen van objecten van een klassetype waarin een operator new is gedefinieerd, wordt die klasse operator new aangeroepen.
Een operator new functie die is gedefinieerd voor een klasse, is een statische lidfunctie (die niet virtueel kan zijn) waarmee de globale operator new functie voor objecten van dat klassetype wordt verborgen. Houd rekening met het geval waarin new wordt gebruikt om geheugen toe te wijzen en in te stellen op een bepaalde waarde:
#include <malloc.h>
#include <memory.h>
class Blanks
{
public:
Blanks(){}
void *operator new( size_t stAllocateBlock, char chInit );
};
void *Blanks::operator new( size_t stAllocateBlock, char chInit )
{
void *pvTemp = malloc( stAllocateBlock );
if( pvTemp != 0 )
memset( pvTemp, chInit, stAllocateBlock );
return pvTemp;
}
// For discrete objects of type Blanks, the global operator new function
// is hidden. Therefore, the following code allocates an object of type
// Blanks and initializes it to 0xa5
int main()
{
Blanks *a5 = new(0xa5) Blanks;
return a5 != 0;
}
Het argument dat tussen haakjes new wordt opgegeven, wordt doorgegeven Blanks::operator new als het chInit argument. De globale operator new functie is echter verborgen, waardoor code zoals het volgende een fout genereert:
Blanks *SomeBlanks = new Blanks;
De compiler ondersteunt lidmatrix new en delete operators in een klassedeclaratie. Voorbeeld:
class MyClass
{
public:
void * operator new[] (size_t)
{
return 0;
}
void operator delete[] (void*)
{
}
};
int main()
{
MyClass *pMyClass = new MyClass[5];
delete [] pMyClass;
}
Gedrag van toewijzingsfouten
De new functie in de standaardbibliotheek van C++ ondersteunt het gedrag dat is opgegeven in de C++-standaard sinds C++98. Als er onvoldoende geheugen is voor een toewijzingsaanvraag, operator new genereert u een std::bad_alloc uitzondering.
Oudere C++-code heeft een null-aanwijzer geretourneerd voor een mislukte toewijzing. Als u code hebt die de niet-gooiende versie van newverwacht, koppelt u uw programma aan nothrownew.obj. Het nothrownew.obj bestand vervangt globaal operator new door een versie die retourneert nullptr als een toewijzing mislukt.
operator new gooit std::bad_allocniet meer . Zie Koppelingsopties voor meer informatie over nothrownew.obj en andere linkeroptiebestanden.
U kunt geen code combineren die controleert op uitzonderingen van globaal operator new met code die controleert op null-aanwijzers in dezelfde toepassing. U kunt echter nog steeds klasse-lokaal operator new maken die zich anders gedraagt. Deze mogelijkheid betekent dat de compiler standaard defensief moet handelen en controles voor null-aanwijzers moet opnemen in new aanroepen. Zie voor meer informatie over een manier om deze compilercontroles /Zc:throwingnewte optimaliseren.
Onvoldoende geheugen verwerken
De manier waarop u test op een mislukte toewijzing van een new expressie, is afhankelijk van of u het standaarduitzonderingsmechanisme gebruikt of dat u een nullptr retour gebruikt. Standaard C++ verwacht dat een allocator een of een klasse genereert std::bad_alloc die is afgeleid van std::bad_alloc. U kunt een dergelijke uitzondering afhandelen, zoals wordt weergegeven in dit voorbeeld:
#include <iostream>
#include <new>
using namespace std;
#define BIG_NUMBER 10000000000LL
int main() {
try {
int *pI = new int[BIG_NUMBER];
}
catch (bad_alloc& ex) {
cout << "Caught bad_alloc: " << ex.what() << endl;
return -1;
}
}
Wanneer u de nothrow vorm van newgebruikt, kunt u testen op een toewijzingsfout, zoals wordt weergegeven in dit voorbeeld:
#include <iostream>
#include <new>
using namespace std;
#define BIG_NUMBER 10000000000LL
int main() {
int *pI = new(nothrow) int[BIG_NUMBER];
if ( pI == nullptr ) {
cout << "Insufficient memory" << endl;
return -1;
}
}
U kunt testen op een mislukte geheugentoewijzing wanneer u het bestand hebt gebruikt nothrownew.obj om globaal operator new te vervangen, zoals hier wordt weergegeven:
#include <iostream>
#include <new>
using namespace std;
#define BIG_NUMBER 10000000000LL
int main() {
int *pI = new int[BIG_NUMBER];
if ( !pI ) {
cout << "Insufficient memory" << endl;
return -1;
}
}
U kunt een handler opgeven voor mislukte aanvragen voor geheugentoewijzing. Het is mogelijk om een aangepaste herstelroutine te schrijven om een dergelijke fout af te handelen. Het kan bijvoorbeeld wat gereserveerd geheugen vrijgeven en vervolgens toestaan dat de toewijzing opnieuw wordt uitgevoerd. Zie _set_new_handler voor meer informatie.
De delete operator
Geheugen dat dynamisch wordt toegewezen met behulp van de new operator, kan worden vrijgemaakt met behulp van de delete operator. Met de verwijderoperator wordt de operator delete functie aangeroepen, waardoor geheugen wordt vrijgemaakt voor de beschikbare pool. Als u de delete operator gebruikt, wordt ook de klassedestructor (indien aanwezig) aangeroepen.
Er zijn globale en class-scoped operator delete functies. Er kan slechts één operator delete functie worden gedefinieerd voor een bepaalde klasse. Als deze is gedefinieerd, wordt de globale operator delete functie verborgen. De globale operator delete functie wordt altijd aangeroepen voor matrices van elk type.
De globale operator delete functie. Er bestaan twee formulieren voor de globale operator delete en klasselidfuncties operator delete :
void operator delete( void * );
void operator delete( void *, size_t );
Slechts één van de voorgaande twee formulieren kan aanwezig zijn voor een bepaalde klasse. Het eerste formulier heeft één argument van het type void *, dat een aanwijzer bevat naar het object om de toewijzing ongedaan te maken. Het tweede formulier, de grootte van deallocatie, heeft twee argumenten: de eerste is een aanwijzer naar het geheugenblok om de toewijzing ongedaan te maken en het tweede is het aantal bytes dat moet worden toegewezen. Het retourtype van beide formulieren is void (operator delete kan geen waarde retourneren).
Het doel van het tweede formulier is om sneller te zoeken naar de juiste groottecategorie van het object dat moet worden verwijderd. Deze informatie wordt vaak niet opgeslagen in de buurt van de toewijzing zelf en wordt waarschijnlijk niet in de cache opgeslagen. Het tweede formulier is handig wanneer een operator delete functie uit een basisklasse wordt gebruikt om een object van een afgeleide klasse te verwijderen.
De operator delete functie is statisch, zodat deze niet virtueel kan zijn. De operator delete functie gehoorzaamt aan toegangsbeheer, zoals beschreven in Member-Access Control.
In het volgende voorbeeld ziet u door de gebruiker gedefinieerde operator new functies die operator delete zijn ontworpen voor het vastleggen van toewijzingen en deallocatie van geheugen:
#include <iostream>
using namespace std;
int fLogMemory = 0; // Perform logging (0=no; nonzero=yes)?
int cBlocksAllocated = 0; // Count of blocks allocated.
// User-defined operator new.
void *operator new( size_t stAllocateBlock ) {
static int fInOpNew = 0; // Guard flag.
if ( fLogMemory && !fInOpNew ) {
fInOpNew = 1;
clog << "Memory block " << ++cBlocksAllocated
<< " allocated for " << stAllocateBlock
<< " bytes\n";
fInOpNew = 0;
}
return malloc( stAllocateBlock );
}
// User-defined operator delete.
void operator delete( void *pvMem ) {
static int fInOpDelete = 0; // Guard flag.
if ( fLogMemory && !fInOpDelete ) {
fInOpDelete = 1;
clog << "Memory block " << cBlocksAllocated--
<< " deallocated\n";
fInOpDelete = 0;
}
free( pvMem );
}
int main( int argc, char *argv[] ) {
fLogMemory = 1; // Turn logging on
if( argc > 1 )
for( int i = 0; i < atoi( argv[1] ); ++i ) {
char *pMem = new char[10];
delete[] pMem;
}
fLogMemory = 0; // Turn logging off.
return cBlocksAllocated;
}
De voorgaande code kan worden gebruikt voor het detecteren van 'geheugenlekken', dat wil gezegd, geheugen dat is toegewezen aan de gratis winkel, maar nooit wordt vrijgemaakt. Om lekken te detecteren, worden de globale new en delete operators opnieuw gedefinieerd om toewijzing en toewijzing van het geheugen te tellen.
De compiler ondersteunt lidmatrix new en delete operators in een klassedeclaratie. Voorbeeld:
// spec1_the_operator_delete_function2.cpp
// compile with: /c
class X {
public:
void * operator new[] (size_t) {
return 0;
}
void operator delete[] (void*) {}
};
void f() {
X *pX = new X[5];
delete [] pX;
}