C++ verwijder vector, objecten, vrij geheugen

Ik ben helemaal in de war met betrekking tot het verwijderen van dingen in C++. Als ik een array van objecten declareer en als ik de clear()-lidfunctie gebruik. Kan ik er zeker van zijn dat het geheugen is vrijgegeven?

Bijvoorbeeld:

tempObject obj1;
tempObject obj2;
vector<tempObject> tempVector;
tempVector.pushback(obj1);
tempVector.pushback(obj2);

Kan ik veilig clear bellen om al het geheugen vrij te maken? Of moet ik herhalen om één voor één te verwijderen?

tempVector.clear();

Als dit scenario wordt gewijzigd in een aanwijzer van objecten, zal het antwoord dan hetzelfde zijn als hierboven?

vector<tempObject> *tempVector;
//push objects....
tempVector->clear();

Antwoord 1, autoriteit 100%

Je kunt clear noemen, en dat vernietigt alle objecten, maar dat maakt het geheugen niet vrij. Het doornemen van de afzonderlijke elementen helpt ook niet (welke actie zou je zelfs voorstellen om de objecten aan te pakken?) Wat je kunt doen is dit:

vector<tempObject>().swap(tempVector);

Dat zal een lege vector creëren zonder toegewezen geheugen en deze verwisselen met tempVector, waardoor de toewijzing van het geheugen effectief wordt opgeheven.

C++11 heeft ook de functie shrink_to_fit, die je zou kunnen aanroepen na de aanroep van clear(), en het zou theoretisch de capaciteit verkleinen om aan de grootte te passen (die nu 0 is). Dit is echter een niet-bindend verzoek en uw implementatie is vrij om het te negeren.


Antwoord 2, autoriteit 30%

Er zijn hier twee verschillende dingen:

  1. levensduur object
  2. opslagduur

Bijvoorbeeld:

{
    vector<MyObject> v;
    // do some stuff, push some objects onto v
    v.clear(); // 1
    // maybe do some more stuff
} // 2

Bij 1wis je v: dit vernietigt alle objecten die het opsloeg. Elk krijgt zijn destructor aangeroepen, als je er een hebt geschreven, en alles dat eigendom is van dat MyObjectwordt nu vrijgegeven.
Echterheeft vector vhet recht om de onbewerkte opslag in de buurt te houden voor het geval je het later wilt.

Als je besluit om er nog wat meer in te stoppen tussen 1en 2, bespaart dit tijd omdat het het oude geheugen kan hergebruiken.

Bij 2gaat de vector vbuiten bereik: alle objecten die je erin hebt geduwd sinds 1worden vernietigd (alsof je had expliciet weer clear genoemd), maar nu is ook de onderliggende opslag vrijgegeven (vzal er niet meer zijn om deze opnieuw te gebruiken).


Als ik het voorbeeld verander zodat veen aanwijzer wordt naar een dynamisch toegewezen vector, moet je deze expliciet verwijderen, omdat de aanwijzer buiten bereik valt bij 2doet dat niet voor jou. Het is in dat geval beter om iets als std::unique_ptrte gebruiken, maar als je dat niet doet en vis gelekt, wordt de toegewezen opslagruimte ook gelekt. Zoals hierboven, moet je ervoor zorgen dat vis verwijderd, en is het aanroepen van clearniet voldoende.


Antwoord 3, autoriteit 20%

vector::clear()maakt geen geheugen vrij dat door de vector is toegewezen om objecten op te slaan; het roept destructors aan voor de objecten die het bevat.

Als de vector bijvoorbeeld een array gebruikt als backing store en momenteel 10 elementen bevat, dan zal het aanroepen van clear()de destructor aanroepen van elk object in de array, maar de backing-array wordt niet ongedaan gemaakt, dus er is nog steeds sizeof(T) * 10bytes toegewezen aan de vector (tenminste). size()zal 0 zijn, maar size()retourneert het aantal elementen in de vector, niet noodzakelijk de grootte van de backing store.

Wat uw tweede vraag betreft, alles wat u toewijst met new, moet u de toewijzing ongedaan maken met delete. Om deze reden onderhoudt u meestal geen aanwijzer naar een vector. Er is zelden (of nooit) een goede reden om dit te doen en je voorkomt dat de vector wordt opgeruimd als deze de ruimte verlaat. Het aanroepen van clear()werkt echter nog steeds op dezelfde manier, ongeacht hoe het is toegewezen.


Antwoord 4, autoriteit 7%

als ik de clear()lidfunctie gebruik. Kan ik er zeker van zijn dat het geheugen is vrijgegeven?

Nee, de lidfunctie clear()vernietigt elk object in de vector, maar laat de capaciteitvan de vector ongewijzigd. Het heeft invloed op de grootte van de vector, maar niet op de capaciteit.

Als u de capaciteit van een vector wilt wijzigen, kunt u de idioom wissen en minimaliseren, dwz een (tijdelijke) lege vector maken en vervolgens beide vectoren verwisselen.


Je kunt gemakkelijk zien hoe elke benadering de capaciteit beïnvloedt. Beschouw de volgende functiesjabloon die de lidfunctie clear()op de doorgegeven vector aanroept:

template<typename T>
auto clear(std::vector<T>& vec) {
   vec.clear();
   return vec.capacity();
}

Beschouw nu de functiesjabloon empty_swap()die de doorgegeven vector verwisselt met een lege:

template<typename T>
auto empty_swap(std::vector<T>& vec) {
   std::vector<T>().swap(vec);
   return vec.capacity();
}

Beide functiesjablonen retourneren de capaciteit van de vector op het moment van retourneren, dan:

std::vector<double> v(1000), u(1000);
std::cout << clear(v) << '\n';
std::cout << empty_swap(u) << '\n';

uitgangen:

1000
0

Antwoord 5, autoriteit 2%

Semantiek verplaatsenzorgt voor een eenvoudige manier om geheugen vrij te maken, door simpelweg de toewijzing (=) operatorvan een lege rvalue:

std::vector<uint32_t> vec(100, 0);
std::cout << vec.capacity(); // 100
vec = vector<uint32_t>();    // Same as "vector<uint32_t>().swap(vec)";    
std::cout << vec.capacity(); // 0

Het is net zo efficiënt als de op “swap()” gebaseerde methode die in andere antwoorden wordt beschreven (in feite doen beide conceptueel hetzelfde). Als het echter om leesbaarheid gaat, is de opdrachtversie beter in het uitdrukken van de bedoeling van de programmeur en is ze beknopter.


Antwoord 6

Je kunt op deze manier geheugen vrijmaken dat door vector wordt gebruikt:

//Removes all elements in vector
v.clear()
//Frees the memory which is not used by the vector
v.shrink_to_fit();

Antwoord 7

Als je de vector keer op keer moet gebruiken en je huidige code verklaart het herhaaldelijk binnen je lus of bij elke functie-aanroep, dan heb je waarschijnlijk onvoldoende geheugen. Ik stel voor dat je het buiten declareert, ze doorgeeft als pointers in je functies en het volgende gebruikt:

my_arr.resize()

Op deze manier blijft u dezelfde geheugenreeks gebruiken voor uw vectoren in plaats van elke keer om nieuwe reeksen te vragen.
Hoop dat dit heeft geholpen.
Opmerking: het formaat wijzigen naar verschillende formaten kan willekeurige waarden toevoegen. Geef indien nodig een geheel getal, zoals 0, door om ze te initialiseren.

Other episodes