creazione di un array di puntatori a oggetti in C++

Voglio creare un array che contiene i puntatori per molti oggetto, ma non riesco a sapere in anticipo il numero di oggetti terrò, il che significa che ho bisogno di allocare dinamicamente la memoria per la matrice. Ho pensato di codice successivo:

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

dove ants è definito come Ant **ants; e Ant è una classe.

Funzionerà?

  • Lo avete già provato?
  • Norum, non posso provare al momento, sto solo iniziando a scrivere il codice, e ho ancora molte parti mancanti.
  • Si potrebbe desiderare di cambiare il tuo ciclo per scorrere da 0 a num_ants, e assegnare le formiche[i]. Non c’è bisogno di compensare il tutto con 1.
  • Non c’è nessun motivo per cui non si poteva provare con un manichino vuoto classe. Basta creare una classe di Pippo che non ha nulla in essa, e utilizzare la stessa logica.
  • Sei sicuro che il codice sopra funziona? Quando scrivo il seguente in Visual Studio, ottengo un errore del compilatore: Ant** formiche = new *Ant[5];
  • alla fine ho usato un vector come illustrato nella risposta selezionata. Qual è l’errore che ricevi?
  • Errore di sintassi: ‘*’. Non dovrebbe essere Ant** ants = new Ant*[numants];? Io non sono un C++ esperto, ma credo che questo sia un errore di battitura.

InformationsquelleAutor SIMEL | 2011-05-04

 

5 Replies
  1. 22

    Funzionerà?

    Sì.

    Tuttavia, se possibile, si dovrebbe utilizzare un vettore:

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

    Se è necessario utilizzare un array allocato dinamicamente quindi preferirei questa sintassi:

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

    Ma dimenticate tutti che. Il codice non è ancora alcun bene, poiché richiede manuale di gestione della memoria. Per la correzione di che si potrebbe modificare il codice:

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

    E meglio di tutti sarebbe semplicemente questo:

    std::vector<Ant> ants(num_ants);
    • Si può davvero assegnare il risultato di new di un array?
    • B: Buona pesca. Risolto.
    • Quindi, fondamentalmente new Ant* [num_ants] è un fake call, in quanto non chiamare il costruttore a tutti giusto? Solo alloca il puntatore dell’array. Ecco perché il new sembra come se esso viene chiamato due volte.
    • Perché “dovrebbe” un std::vector essere utilizzato?
    • Vale la pena notare che se la Formica di classe è la classe base per le altre classi e istanze di queste classi derivate possono anche essere memorizzati in un array di Formiche quindi il secondo metodo (std::vector<Ant>) non si adatta.
  2. 4
    std::vector<Ant> ants(num_ants);
    ants.resize(new_num_ants);
    • Se l’OP vuole utilizzare i puntatori per le Formiche, la dichiarazione sarebbe: std::vector<Ant *> ant_pointers(num_ants);
    • È inoltre necessario utilizzare std::generate per new tutti i rispettivi elementi.
    • I down hanno votato perché l’OP direttamente menzionato voleva usare i puntatori, che come @ThomasMatthews detto, ha bisogno di una diversa dichiarazione. La tua risposta è buona per un caso diverso però.
    • Io con voto positivo perché OP a quanto pare non sa di array di oggetti di essere una scelta migliore
  3. 3

    Non si ha realmente bisogno di tenere puntatori per gli articoli? Se è possibile utilizzare oggetti di valore, con un approccio più semplice è quello di utilizzare un vettore: std::vector<Ant> ants(num_ants);. Quindi non solo non è necessario scrivere un loop, ma non è necessario preoccuparsi di perdite di memoria da raw puntatori e altri oggetti voci di gestione.

    Se avete bisogno di puntatori a oggetti di dire soddisfare un’API è ancora possibile utilizzare vector per il contenitore esterno e allocare gli oggetti manualmente.

    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());
  4. 2
    std::vector<Ant*> ants( num_ants );
    for ( int i = 0; i != num_ants; ++ i ) {
        ants[i] = new Ant;
    }

    O se non sai come molte in anticipo:

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

    D’altra parte, penso che dovresti chiedere a te stesso se
    Ant è un tipo di entità o di un valore. Se è un valore, ti
    probabilmente si desidera saltare i puntatori e l’allocazione dinamica;
    se si tratta di un tipo di entità, si dovrà prendere in considerazione la durata di
    l’oggetto, quando e dove sarà eliminata.

  5. 2

    Sì che l’idea generale. Tuttavia, ci sono alternative. Sei sicuro che hai bisogno di un array di puntatori? Un array di oggetti di classe Ant può essere sufficiente. La si avrebbe solo bisogno di allocare la matrice:

    Ant *ants = new Ant[num_ants];

    In generale, si dovrebbe preferire l’utilizzo std::vector all’utilizzo di un array. Un vettore può crescere in base alle esigenze, e che gestirà la gestione della memoria per voi.

    Nel codice che hai postato, si dovrebbe eliminare ogni elemento di ants in un ciclo, e quindi eliminare la matrice stessa, delete [] ant. Tenete a mente la differenza tra delete e delete [].

    Un punto in più, dal momento che gli indici degli array in C++ sono basato su 0, la seguente convenzione viene utilizzato per scorrere gli elementi:

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

    Questo rende il codice molto più leggibile.

Lascia un commento