Een array van objectaanwijzers C++

Ik wil een array maken die aanwijzingen op veel objecten bevat, maar ik weet niet van tevoren het aantal objecten dat ik vasthoudt, wat betekent dat ik het geheugen voor de array dynamisch moet toewijzen. Ik heb aan de volgende code gedacht:

ants = new *Ant[num_ants];
for (i=1;i<num_ants+1;i++)
{
    ants[i-1] = new Ant();
}

waar antsis gedefinieerd als Ant **ants;en Antis een klasse.

Werkt het?


Antwoord 1, Autoriteit 100%

Werkt het?

Ja.

Indien mogelijk moet u echter een vector gebruiken:

#include <vector>
std::vector<Ant*> ants;
for (int i = 0; i < num_ants; ++i) {
    ants.push_back(new Ant());
}

Als u een dynamisch toegewezen array moet gebruiken, dan zou ik deze syntaxis verkiezen:

typedef Ant* AntPtr;
AntPtr * ants = new AntPtr[num_ants];
for (int i = 0; i < num_ants; ++i) {
    ants[i] = new Ant();
}

Vergeet alles. De code is nog steeds niet goed, omdat het handmatig geheugenbeheer vereist. Om te bepalen of u uw code kunt wijzigen naar:

std::vector<std::unique_ptr<Ant>> ants;
for (auto i = 0; i != num_ants; ++i) {
    ants.push_back(std::make_unique<Ant>());
}

en het beste van alles zou dit eenvoudig zijn:

std::vector<Ant> ants(num_ants);

Antwoord 2, Autoriteit 15%

std::vector<Ant> ants(num_ants);
ants.resize(new_num_ants);

Antwoord 3, autoriteit 12%

Ja, dat is het algemene idee. Er zijn echter alternatieven. Weet je zeker dat je een array van pointers nodig hebt? Een array van objecten van de klasse Antkan voldoende zijn. U hoeft alleen de array toe te wijzen:

Ant *ants = new Ant[num_ants];

Over het algemeen zou u liever std::vectorgebruiken in plaats van een array. Een vector kan naar behoefte groeien en zal het geheugenbeheer voor u regelen.

In de code die je hebt gepost, zou je elk element van antsin een lus moeten verwijderen, en dan de array zelf verwijderen, delete [] ant. Houd rekening met het verschil tussen deleteen delete [].

Nog een punt, aangezien array-indices in C++ op 0 zijn gebaseerd, wordt de volgende conventie gebruikt om de elementen te herhalen:

for (i=0; i<num_ants; i++)
{
    ants[i] = new Ant();
}

Dit maakt code veel leesbaarder.


Antwoord 4, autoriteit 12%

Moet je echt aanwijzersnaar de items houden? Als u objecten op waarde kunt gebruiken, is het veel eenvoudiger om een vector te gebruiken: std::vector<Ant> ants(num_ants);. Dan hoeft u niet alleen geen looping te schrijven, maar hoeft u zich ook geen zorgen te maken over geheugenlekken van onbewerkte pointers en andere objectbeheeritems.

Als je objectaanwijzers nodig hebt om aan een API te voldoen, kun je nog steeds vectorgebruiken voor de buitenste container en de objecten handmatig toewijzen.

struct CreateAnt
{
    Ant* operator()() const { return new Ant; }
};
std::vector<Ant*> ants(num_ants);  // Create vector with null pointers.
std::generate(ants.begin(), ants.end(), CreateAnt());

Antwoord 5, autoriteit 8%

std::vector<Ant*> ants( num_ants );
for ( int i = 0; i != num_ants; ++ i ) {
    ants[i] = new Ant;
}

Of als u niet van tevoren weet hoeveel:

std::vector<Ant*> ants;
while ( moreAntsNeeded() ) {
    ants.push_back( new Ant );
}

Aan de andere kant denk ik dat je jezelf moet afvragen of
Antis een entiteitstype of een waarde. Als het een waarde is, zul je
wil waarschijnlijk de pointers en de dynamische toewijzing overslaan;
als het een entiteitstype is, moet u rekening houden met de levensduur van
het object, en wanneer en waar het zal worden verwijderd.

Other episodes