2011-09-23 13 views
16

Kod folowing pokazuje wyjście nie oczekuje:Czy wektor STL wywołuje destruktor obiektu nieprzypisanego?

class test 
{ 
    public: 
    test() 
    { 
     std::cout << "Created" << (long)this << std::endl; 
    } 
    ~test() 
    { 
     std::cout << "Destroyed" << (long)this << std::endl; 
    } 
}; 

int main(int argc, char** argv) 
{ 
    std::vector<test> v; 
    test t; 
    v.push_back(t); 

    return EXIT_SUCCESS; 
} 

Po uruchomieniu pokazuje:

Created-1077942161 
Destroyed-1077942161 
Destroyed674242816 

myślę drugi "Destroyed" wyjście nie powinno tam być. Kiedy nie używam wektora, wynikiem jest linia Jedna utworzona i jedna Zniszczona zgodnie z oczekiwaniami. Czy to zachowanie jest normalne?

(To jest skompilowany z GCC na systemie FreeBSD)

+3

+1 dla [SSCCE] (http://sscce.org/) – Flexo

+3

Aby wydrukować wskaźniki, najlepiej jest rzutować na wskaźnik pustych obiektów: 'std :: cout << (void *) this << std :: endl ; '. –

+0

Również zwracanie 'EXIT_SUCCESS' jest opcjonalne. Możesz pominąć wartość zwracaną w 'main', zwróci ona' 0' (która zmieni się w którąkolwiek z liczb oznacza "normalne zakończenie" dla twojej platformy). –

Odpowiedz

31

Wszystko jest tak jak być powinno: istnieje zmienna lokalna t, który zostanie utworzony, a następnie zniszczone pod koniec main(), a tam v[0], który dostaje utworzone i zniszczone pod koniec main().

Nie widzisz utworzenia v[0], ponieważ dzieje się tak przez kopiowanie lub przenoszenie konstruktora, którego klasa testowa nie zapewnia. (Tak kompilator zapewnia jeden dla Ciebie, ale bez wyjścia.)


Dla celów testowych jest przydatny do pisania dla siebie raz na zawsze klasie testowej, która zawiera wszystkie możliwe konstruktorów, destruktorów, przyporządkowanie i operatorów swapowe i drukuje linię diagnostyczną w każdym z nich, dzięki czemu można obserwować, jak zachowują się obiekty, gdy są używane w kontenerach i algorytmach.

+0

Nie może to być "move constructor". – Nawaz

+0

@Namaz: Racja. Aby użyć konstruktora ruchu, musisz powiedzieć: eitehr 'v.push_back (std :: move (t))' lub 'v.push_back (test())'. Obaj jednak utworzą podobną sekwencję komunikatów. –

29
#include <cstdlib> 
#include <vector> 
#include <iostream> 

class test 
{ 
    public: 
    test() 
    { 
     std::cout << "Created " << (long)this << std::endl; 
    } 
    test(const test&) 
    { 
     std::cout << "Copied " << (long)this << std::endl; 
    } 
    ~test() 
    { 
     std::cout << "Destroyed " << (long)this << std::endl; 
    } 
}; 

int main(int argc, char** argv) 
{ 
    std::vector<test> v; 
    test t; 
    v.push_back(t); 

    return EXIT_SUCCESS; 
} 

wyjściowa:

Created -1076546929 
Copied 147865608 
Destroyed -1076546929 
Destroyed 147865608 

std::vector::push_back kopiuje obiektów t, widać konstruktor kopiujący jest wywoływana przez powyższy kod.

2

Wektor trzyma kopię t, dlatego po wywołaniu push_back masz dwie wersje t ... jedną na stosie i jedną w wektorze. Ponieważ wersja wektorowa została stworzona przez kopiującego konkurenta, nie widzisz monitu "Utworzono ..." dla tego obiektu ... ale nadal musi on zostać zniszczony, gdy pojemnik wektorowy wychodzi poza zasięg, dlatego dostajesz dwa Wiadomości "Zniszczone ...".

Powiązane problemy