Zoeken…


Syntaxis

  • : :( opt ) new ( expression-list ) ( opt ) new-type-id new-initializer ( opt )
  • : :( opt ) new ( expression-list ) ( opt ) ( type-id ) new-initializer ( opt )
  • : :( opt ) cast-expressie verwijderen
  • : :( opt ) [] cast-expression verwijderen
  • std :: unique_ptr < type-id > var_name (nieuw type-id ( opt )); // C ++ 11
  • std :: shared_ptr < type-id > var_name (nieuw type-id ( opt )); // C ++ 11
  • std :: shared_ptr < type-id > var_name = std :: make_shared < type-id > ( opt ); // C ++ 11
  • std :: unique_ptr < type-id > var_name = std :: make_unique < type-id > ( opt ); // C ++ 14

Opmerkingen

Een leidende :: dwingt de nieuwe of verwijder-operator op te zoeken in globaal bereik, en vervangt overbelaste klassespecifieke nieuwe of verwijder-operators.

De optionele argumenten na het new trefwoord worden meestal gebruikt om plaatsing nieuw te noemen, maar kunnen ook worden gebruikt om extra informatie door te geven aan de allocator, zoals een tag die vraagt dat geheugen wordt toegewezen uit een gekozen pool.

Het toegewezen type wordt meestal expliciet gespecificeerd, bijv. new Foo , maar kan ook worden geschreven als auto (sinds C ++ 11) of decltype(auto) (sinds C ++ 14) om het uit de initialisatie af te leiden.

Initialisatie van het toegewezen object vindt plaats volgens dezelfde regels als initialisatie van lokale variabelen. In het bijzonder wordt het object standaard geïnitialiseerd als het initialisatieprogramma niet wordt weggelaten en wanneer er dynamisch een scalair type of een reeks scalair type wordt toegewezen, is er geen garantie dat het geheugen op nul wordt gezet.

Een arrayobject dat door een nieuwe expressie is gemaakt, moet worden vernietigd met delete[] , ongeacht of de nieuwe expressie met [] is geschreven of niet. Bijvoorbeeld:

using IA = int[4];
int* pIA = new IA;
delete[] pIA;  // right
// delete pIA;  // wrong

stack

De stapel is een klein geheugengebied waarin tijdelijke waarden worden geplaatst tijdens de uitvoering. Gegevens toewijzen aan de stapel is erg snel in vergelijking met heap-toewijzing, omdat al het geheugen hiervoor is toegewezen.

int main() {
    int a = 0; //Stored on the stack
    return a;
}

De stapel wordt genoemd omdat ketens van functieaanroepen hun tijdelijke geheugen op elkaar "gestapeld" hebben, waarbij elk een afzonderlijk klein gedeelte van het geheugen gebruikt.

float bar() {
    //f will be placed on the stack after anything else
    float f = 2;
    return f;
}

double foo() {
    //d will be placed just after anything within main()
    double d = bar();
    return d;
}

int main() {
    //The stack has no user variables stored in it until foo() is called
    return (int)foo();
}

Gegevens die op de stapel zijn opgeslagen, zijn alleen geldig zolang het bereik dat de variabele heeft toegewezen nog actief is.

int* pA = nullptr;

void foo() {
    int b = *pA;
    pA = &b;
}

int main() {
    int a = 5;
    pA = &a;
    foo();
    //Undefined behavior, the value pointed to by pA is no longer in scope
    a = *pA;
}

Gratis opslag (heap, dynamische toewijzing ...)

De term 'heap' is een algemene computerterm die een geheugengebied betekent waaruit delen kunnen worden toegewezen en gedealloceerd onafhankelijk van het geheugen dat door de stapel wordt geleverd .

In C++ verwijst de standaard naar dit gebied als de Free Store die als een meer accurate term wordt beschouwd.

Gebieden van geheugen toegewezen vanuit de Free Store kunnen langer leven dan de oorspronkelijke scope waarin het werd toegewezen. Gegevens die te groot zijn om op de stapel te worden opgeslagen, kunnen ook worden toegewezen vanuit de Free Store .

Onbewerkte geheugen kan worden toegewezen en toegewezen door de nieuwe en verwijder sleutelwoorden.

float *foo = nullptr;
{
    *foo = new float; // Allocates memory for a float
    float bar;              // Stack allocated 
} // End lifetime of bar, while foo still alive

delete foo;          // Deletes the memory for the float at pF, invalidating the pointer
foo = nullptr;       // Setting the pointer to nullptr after delete is often considered good practice

Het is ook mogelijk om arrays met een vaste grootte toe te wijzen aan nieuw en te verwijderen , met een iets andere syntaxis. Array-toewijzing is niet compatibel met niet-array-toewijzing en het combineren van de twee leidt tot heap-corruptie. Door een array toe te wijzen, wordt ook geheugen toegewezen om de grootte van de array te volgen voor latere verwijdering op een door de implementatie gedefinieerde manier.

// Allocates memory for an array of 256 ints
int *foo = new int[256];
// Deletes an array of 256 ints at foo
delete[] foo;

Bij het gebruik van nieuwe en verwijderen in plaats malloc en gratis , zal de constructeur en destructor word uitgevoerd (vergelijkbaar met basis objecten stack). Dit is de reden waarom nieuw en verwijderen de voorkeur hebben boven malloc en gratis .

struct ComplexType {
    int a = 0;

    ComplexType() { std::cout << "Ctor" << std::endl; }
    ~ComplexType() { std::cout << "Dtor" << std::endl; }
};

// Allocates memory for a ComplexType, and calls its constructor
ComplexType *foo = new ComplexType();
//Calls the destructor for ComplexType() and deletes memory for a Complextype at pC
delete foo;
C ++ 11

Vanaf C ++ 11 wordt het gebruik van slimme aanwijzers aanbevolen om eigendom aan te geven.

C ++ 14

C ++ 14 voegde std::make_unique aan de STL, veranderde de aanbeveling om std::make_unique of std::make_shared plaats van naakt nieuw te gebruiken en te verwijderen .

Plaatsing nieuw

Er zijn situaties waarin we niet op Free Store willen vertrouwen voor het toewijzen van geheugen en we aangepaste geheugentoewijzingen met new willen gebruiken.

Voor deze situaties kunnen we Placement New gebruiken, waar we de `nieuwe 'operator kunnen vertellen om geheugen toe te wijzen vanuit een vooraf toegewezen geheugenlocatie

Bijvoorbeeld

int a4byteInteger;

char *a4byteChar = new (&a4byteInteger) char[4];

In dit voorbeeld is het geheugen met a4byteChar 4 byte toegewezen aan 'stack' via de variabele geheel getal a4byteInteger .

Het voordeel van dit soort geheugentoewijzing is het feit dat programmeurs de toewijzing beheren. Omdat in het bovenstaande voorbeeld a4byteInteger op de stapel wordt toegewezen, hoeven we geen expliciete aanroep te doen om 'a4byteChar' te verwijderen.

Hetzelfde gedrag kan ook worden bereikt voor dynamisch toegewezen geheugen. Bijvoorbeeld

int *a8byteDynamicInteger = new int[2];

char *a8byteChar = new (a8byteDynamicInteger) char[8];

In dit geval verwijst de geheugenpointer van a8byteChar naar dynamisch geheugen toegewezen door a8byteDynamicInteger . In dit geval moeten we echter expliciet delete a8byteDynamicInteger om het geheugen vrij te maken

Een ander voorbeeld voor C ++ Class

struct ComplexType {
    int a;

    ComplexType() : a(0) {}
    ~ComplexType() {}
};

int main() {
    char* dynArray = new char[256];

    //Calls ComplexType's constructor to initialize memory as a ComplexType
    new((void*)dynArray) ComplexType();

    //Clean up memory once we're done
    reinterpret_cast<ComplexType*>(dynArray)->~ComplexType();
    delete[] dynArray;

    //Stack memory can also be used with placement new
    alignas(ComplexType) char localArray[256]; //alignas() available since C++11

    new((void*)localArray) ComplexType();

    //Only need to call the destructor for stack memory
    reinterpret_cast<ComplexType*>(localArray)->~ComplexType();

    return 0;
}


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow