2011-09-11 22 views
17

Jaki jest właściwy sposób wypychania nowego elementu obiektu na std::vector? Chcę, aby dane zostały przydzielone w wektorze. Czy to skopiuje obiekt newradio do wektora, a następnie pozbędzie się newradio, gdy wyjdzie poza zasięg (na przykład ze stosu)?C++ vector push_back

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

A potem, kiedy zwolnić obiekt zawierający m_radios, to wszystko za darmo pamięć przydzieloną przez wektor?

Odpowiedz

29

std::vector zarządza własną pamięcią. Oznacza to, że gdy wywoływany jest destruktor wektora, pamięć utrzymywana przez wektor jest zwalniana. std::vector wywołuje także destruktor obiektu po jego usunięciu (poprzez erase, pop_back, clear lub destruktora wektora).

Kiedy to zrobić:

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

dodać kopię newradio (utworzony za pomocą Radio „s kopiować konstruktora) do wektora. newradio zostanie zniszczony, gdy zniknie z zakresu, a kopia zostanie zniszczona, gdy zostanie usunięta z wektora (jak dla dowolnego obiektu).

To ważny punkt: std::vector wyłącznie magazynuje kopie obiektu, co oznacza, że ​​obiekt musi mieć znaczący konstruktor kopiujący (i operator przypisania, ale to inna kwestia). Jeśli masz wektor wskaźników, sam wskaźnik zostanie skopiowany, a nie to, co wskazuje. Należy zauważyć, że to zachowanie jest takie samo dla każdego standardowego kontenera (np. std::list lub std::set).

Zgodnie z ogólną zasadą, jeśli nie używasz wskaźników, nie musisz się martwić o samo zwolnienie pamięci.

C++ 11, najbardziej standardowe pojemniki (w tym vector) mają sposób emplace_back budujące obiekt zamiast na końcu pojemnika. Pobiera kilka parametrów i wywołuje konstruktora, który najlepiej pasuje do tych parametrów (lub kończy się niepowodzeniem, jeśli nie istnieje taki konstruktor), używając wspomnianego konstruktora do utworzenia obiektu, bez żadnej kopii, na końcu kontenera. Więc, powyższy kod może być zapisane jako:

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

także w C++ 11, pojemniki są zwykle przenieść świadomość, więc nie wymagają już obiektów do copiable: jeśli są ruchomy, a następnie kontener przeniesie swoją zawartość zgodnie z wymaganiami (na przykład podczas realokacji). Kopiowane typy są nadal wymagane, jeśli chcesz skopiować wektor.

+3

Choć poprawne w czasie, to odpowiedź może wykorzystać aktualizacji przywołujące 'emplace_back' –

+0

bardzo dobry punkt Mr Duck. –

0

Tak, radioNum będzie kopiowane do m_radios. Tak długo, jak nie jesteś zwolniony, gdy pojawi się newradio.~Radio(); (poza zakresem), jest OK. Jeśli m_radios lub podklasa używa wskaźników, musisz ustawić przełącznik na smart pointers (shared_ptr).

Gdy wykracza poza zakres, destruktor jest automatycznie wywoływany, a wszystkie rzeczy przechowywane przez użytkownika są zwalniane.

1

Tak, naciskając newRadio przesyła kopię obiektu Radio do wektora. Nie musisz też zwolnić wektora, ponieważ jest on lokalny, więc zostanie zniszczony, gdy znikniesz z jego zasięgu. Jeśli na przykład napisałeś

Następnie musisz zwolnić tę pamięć, wywołując destruktor wektora ręcznie.

3

push_back() będzie przechowywać kopię swojego argumentu w wektorze. Dopóki Radio implementuje odpowiednią semantykę wartości, nie będzie z tym żadnych problemów.

0

W uzupełnieniu do innych odpowiedzi, które sprawdzają, czy obiekt jest kopiowany do pojemnika przy użyciu push_back poprzez wywołania konstruktora kopii, można również pamiętać o nową funkcjonalność emplace_back dodaną z c++0x.

Zadzwoń pod numer emplace_back, aby pominąć tworzenie dowolnych tymczasowych obiektów i bezpośrednio skonstruować obiekt w miejscu wewnątrz kontenera. emplace_back jest varardic funkcja szablon, który akceptuje parametry chcesz przekazać do konstruktora swojego obiektu, a więc w tym przypadku:

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

nie stworzy żadnych temporaries pośrednich. Może to być pomocne, jeśli twoje obiekty są kosztowne do skopiowania.

Mam nadzieję, że to pomoże.

0

Domyślnie std :: vector zarządza samą pamięcią przy użyciu konstruktora kopii podstawowej klasy. Działa to tak, jakby element wektorowy był zmienną lokalną (gdy wektor wykracza poza zakres, element ulega destrukcji).

Jeśli nie chcesz tego zachowania, możesz użyć wektora wskaźnika lub boost :: ptr_vector.

1

Spróbuj tego:

#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"; 


} 

wyjściowa:

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 
+2

Edytuj odpowiedź i sformatuj kod, aby był czytelny. – kleopatra

+1

Nie rozumiem, co się dzieje w tym kodzie: S może ktoś wyjaśnić? Dzięki –

Powiązane problemy