it-swarm.it

Vettore C++ Push_back

Qual è il modo corretto di spingere un nuovo elemento oggetto su un std::vector? Voglio che i dati vengano assegnati nel vettore. Sarà questo copia l'oggetto newradio nel vettore e quindi eliminare newradio quando esce dall'ambito (ad esempio fuori dallo stack)?

vector<Radio> m_radios;
Radio newradio(radioNum);
m_radios.Push_back(newradio);

E poi quando libererò l'oggetto contenente m_radios, questo libererà tutta la memoria allocata dal vettore?

18
user623879

std::vector gestisce la propria memoria. Ciò significa che, quando viene invocato il distruttore di un vettore, viene rilasciata la memoria trattenuta dal vettore. std::vector richiama anche il distruttore di un oggetto quando viene rimosso (tramite erase, pop_back, clear o il distruttore del vettore).

Quando lo fai:

Radio newradio(radioNum);
m_radios.Push_back(newradio);

Aggiungi una copia di newradio (creata usando il costruttore di copie Radio) al vettore. newradio verrà distrutto quando esce dal campo di applicazione e la copia verrà distrutta quando viene rimossa dal vettore (come per qualsiasi oggetto).

Questo è un punto importante: std::vector memorizza solo copie di un oggetto, il che significa che l'oggetto deve avere un costruttore di copia significativo (e un operatore di assegnazione, ma questo è un altro problema). Se hai un vettore di puntatori, allora il puntatore stesso verrà copiato e non quello a cui punta. Si noti che questo comportamento è lo stesso per ogni contenitore standard (come std::list o std::set).

Come regola generale, se non si utilizzano i puntatori, non è necessario preoccuparsi di rilasciare la memoria da soli.

In C++ 11, la maggior parte dei contenitori standard (incluso vector) ha un metodo emplace_back che costruisce un oggetto in place alla fine del contenitore. Ci vuole un po 'di parametri e chiama il costruttore che meglio corrisponde a quei parametri (o fallisce se non esiste un tale costruttore), usando detto costruttore per creare l'oggetto, senza alcuna copia, alla fine del contenitore. Quindi, il codice sopra potrebbe essere riscritto come:

m_radios.emplace_back(radioNum); // construct a Radio in place, 
                                 // passing radioNum as the constructor argument

Anche in C++ 11, i contenitori sono in genere move aware , quindi non richiedono più la copiabilità degli oggetti: se sono mobili , il contenitore sposterà il suo contenuto come richiesto (ad esempio durante le riallocazioni , per esempio). I tipi copiabili sono ancora necessari se si desidera copiare il vettore.

33

Push_back() memorizzerà una copia del suo argomento all'interno del vettore. Finché Radio implementa la semantica del valore appropriato, non ci saranno problemi con esso.

4
K-ballo

Sì spingendo newRadio spingerà una copia dell'oggetto Radio nel vettore. Inoltre, non è necessario liberare il vettore perché è solo locale, quindi verrà distrutto una volta fuori dal suo ambito. Se ad esempio hai scritto

vector<Radio> *m_radios = new vector<Radio>();

Quindi dovresti liberare quella memoria chiamando manualmente il distruttore di vettori.

1
Jesus Ramos

Prova questo:

#include<iostream.h>
#include<vector.h>

class base
{
int i;
public:

    base(int z=0){i=z;cout<<"okk constructor "<<i<<" called\n";}
    base(const base& b1){i=b1.i;cout<<"copy constructor "<<i<<" called\n";}
    void display(){cout<<" val is "<<i<<" \n";}
    ~base(){cout<<"destructor of "<<i<<" base called\n";}
};


    int main()
    {
        cout<<"before anything\n";
        vector<base> basev;
        base baseobj1(1);
        base baseobj2(2);
        base baseobj3(3);
        base baseobj4(4);
        base baseobj5(5);
        base baseobj6(6);
        base baseobj7(7);
        base baseobj8(8);
        base baseobj9(9);
        base baseobj10(10);


        basev.Push_back(baseobj1);
        cout<<"second Push back\n";
        basev.Push_back(baseobj2);
        cout<<"third Push back\n";
        basev.Push_back(baseobj3);
        cout<<"fourth Push back\n";
        basev.Push_back(baseobj4);
        cout<<"fifth Push back\n";
        basev.Push_back(baseobj5);
        cout<<"sixth Push back\n";
        basev.Push_back(baseobj6);
        cout<<"seventh Push back\n";
        basev.Push_back(baseobj7);
        cout<<"eighth Push back\n";
        basev.Push_back(baseobj8);
        cout<<"ninth Push back\n";
        basev.Push_back(baseobj9);
        cout<<"10th Push back\n";
        basev.Push_back(baseobj10);
        cout<<"after all Push back\n";


        cout<<"before clear\n";
        basev.clear();
        cout<<"after clear\n";


}

produzione:

before anything
okk constructor 1 called
okk constructor 2 called
okk constructor 3 called
okk constructor 4 called
okk constructor 5 called
okk constructor 6 called
okk constructor 7 called
okk constructor 8 called
okk constructor 9 called
okk constructor 10 called
copy constructor 1 called
second Push back
copy constructor 1 called
copy constructor 2 called
destructor of 1 base called
third Push back
copy constructor 1 called
copy constructor 2 called
copy constructor 3 called
destructor of 1 base called
destructor of 2 base called
fourth Push back
copy constructor 4 called
fifth Push back
copy constructor 1 called
copy constructor 2 called
copy constructor 3 called
copy constructor 4 called
copy constructor 5 called
destructor of 1 base called
destructor of 2 base called
destructor of 3 base called
destructor of 4 base called
sixth Push back
copy constructor 6 called
seventh Push back
copy constructor 7 called
eighth Push back
copy constructor 8 called
ninth Push back
copy constructor 1 called
copy constructor 2 called
copy constructor 3 called
copy constructor 4 called
copy constructor 5 called
copy constructor 6 called
copy constructor 7 called
copy constructor 8 called
copy constructor 9 called
destructor of 1 base called
destructor of 2 base called
destructor of 3 base called
destructor of 4 base called
destructor of 5 base called
destructor of 6 base called
destructor of 7 base called
destructor of 8 base called
10th Push back
copy constructor 10 called
after all Push back
before clear
destructor of 1 base called
destructor of 2 base called
destructor of 3 base called
destructor of 4 base called
destructor of 5 base called
destructor of 6 base called
destructor of 7 base called
destructor of 8 base called
destructor of 9 base called
destructor of 10 base called
after clear
destructor of 10 base called
destructor of 9 base called
destructor of 8 base called
destructor of 7 base called
destructor of 6 base called
destructor of 5 base called
destructor of 4 base called
destructor of 3 base called
destructor of 2 base called
destructor of 1 base called
1
Monotosh Mondal

Di default, std :: vector gestisce la memoria stessa usando il costruttore di copie della classe sottostante. Quindi agisce un po 'come se l'elemento vettoriale fosse una variabile locale (quando il vettore esce dal campo di applicazione, l'elemento viene distrutto).

Quando non vuoi questo comportamento, puoi usare un vettore di puntatore o boost :: ptr_vector.

0
nuKs

Yup, radioNum sarà copiato in m_radios. Finché non stai deallocando i puntatori quando si verifica newradio.~Radio(); (fuori ambito), va bene. Se m_radios o una sottoclasse utilizza i puntatori, dovrai passare a puntatori intelligenti (shared_ptr).

Quando m_radios esce dall'ambito, il distruttore viene automaticamente chiamato e tutte le cose std::vector in attesa vengono liberate.

0
Mateen Ulhaq

Oltre alle altre risposte che verificano che l'oggetto sia copiato nel contenitore quando si utilizza Push_back tramite chiamate al costruttore di copie, si potrebbe anche tenere a mente la nuova funzionalità emplace_back aggiunta con c++0x.

Chiamando emplace_back è possibile evitare la creazione di oggetti temporanei e creare direttamente l'oggetto sul contenitore direttamente nel contenitore. emplace_back è una funzione di template varardico che accetta i parametri che dovresti passare al costruttore del tuo oggetto, quindi in questo caso:

std::vector<Radio> m_radios;
m_radios.emplace_back(radioNum);

non creerà alcun temporaneo intermedio. Questo può essere utile se i tuoi oggetti sono costosi da copiare.

Spero che questo ti aiuti.

0
Darren Engwirda