2011-09-08 8 views
6

Mam pytanie dotyczące wydajności std :: vector <> w C++. Czy szybsze jest ponowne użycie tego samego wektora przez wywołanie metody clear() lub szybsze odtworzenie wektora?co jest szybsze: odtworzyć lub wyczyścić()?

Poniższy przykład ma prawdziwy kod życie, to tylko do tworzenia jasne, co jest pytanie:

//Example ONE: is this faster 
std::vector<int> foo; 
for(int i = 0; i < 100; ++i) 
{ 
    foo.clear(); 
    for(int j = 0; j < 100; ++j) 
    { 
     foo.push_back(i+j); 
    } 
} 

//Example TWO: or is that faster? 
for(int i = 0; i < 100; ++i) 
{ 
    std::vector<int> foo; 
    for(int j = 0; j < 100; ++j) 
    { 
     foo.push_back(i+j); 
    } 
} 
+0

Czy te rzeczy nie są zależne od implementacji? –

+6

Profiluj to. Boooooring! –

+3

Dlaczego wszystkie spadki? – Daniel

Odpowiedz

7

clear() nie może przez umowę zwalnianie pamięci vector, zamiast po prostu ustawia wewnętrzną „rozmiar” Flag do 0, dzięki czemu metoda będzie szybsza.

+1

Powiedziałbym, że bardziej niż "nieznacznie". –

+1

Nie znam żadnej implementacji, która zwalnia pamięć. –

+0

@David: Tworzenie nowego wektora to robi! : D [edytuj: tak, ok, pozwalając staremu umrzeć to robi] –

0

Przykład 2 ma powtarzające się alokacje sterty dla tablicy wewnątrz std :: vector. Przykład 1 jest szybszy, ponieważ pozwala uniknąć wielokrotnego przydzielania pamięci na stercie, chyba że wektor wymaga wewnętrznej zmiany rozmiaru.

+0

's/przydzielanie pamięci na stertę/pamięć dynamicznie alokującą /' –

0

Będziesz musiał uruchomić testy porównawcze dla swojego kompilatora. Metody clear() i "przydzielić" są zależne od implementacji.

+0

To, że pojemność wektora nigdy się nie zmniejsza, w ogóle nie zależy od implementacji. [edytuj: chociaż C++ 11 _nie ma 'shrink_to_fit'] –

+0

@Tomalak: Myślałem o tym. W standardzie nie ma żadnej klauzuli, która uniemożliwiałaby implementację rzeczywistego uwolnienia pamięci. Wektor, który * kurczy się *, byłby trudniejszy do wdrożenia w wielu przypadkach (przy zachowaniu * zamortyzowanego stałego czasu * kosztu 'push_back'), ale nie sądzę, że byłby * niemożliwy *, i że dla ogólnego przypadku 'erase', ze specyfikacją' clear() 'Nie widzę żadnego powodu, dla którego zgodna implementacja nie mogłaby zwolnić pamięci (potem znowu, nie przeszedłem standardu szukającego tego konkretnego przypadku ...) –

+0

@David: Też się nad tym zastanawiam. Nie widzę żadnej gwarancji, że 'clear' * musi * wywołać' reserve'. Wydaje mi się to dość silnie implikowane, ale nie jest to stwierdzone. –

2

To zależy od realizacji std::vector w C++ biblioteki standardowej, której używasz, ale jest prawdopodobne, że pierwszy przypadek będzie szybciej, ponieważ większość implementacji nie faktycznie bezpłatne przydzieloną pamięć podczas rozmowy std::vector::clear. Tak więc pierwszy nie wykonuje powtórnych alokacji, gdy pętla wewnętrzna zostanie wykonana za pierwszym razem.

0

zarówno wyczyścić wektor i zmniejszenia jego zdolności do minimum implementacji, w Scott Meyers zaleca trick wymiany:

std::vector<int>().swap(foo); 

byłoby również szybciej niż iteracja wektora z ręcznie walcowane pętli do przywrócić jej zawartość.

1

Tak. Najpierw jest szybszy, prawdopodobnie. To zależy. Jedyną użyteczną odpowiedzią jest profilowanie własnego kodu we własnym środowisku.

Spróbuj profilować swój kod, aby zobaczyć, co się stanie. Kompilowanie your program at ideone ujawnia, że ​​dla jednego konkretnego kompilatora/os/machine/run Twój pierwszy przykład jest 4x szybszy.

I this program pokazuje rozwiązanie pośrednie, które idzie szybciej niż # 2, wolniej niż # 1, dla tego konkretnego kompilatora/os/machine/run.

0

W tym konkretnym przypadku przypadek ponownego użycia będzie prawdopodobnie szybszy na większości komputerów. Przechowujesz prymitywne dane, które nie wymagają destrukcji (lub nawet destruktora). Z drugiej strony, jeśli wektor zawiera obiekty inne niż POD, każdy element zostanie zniszczony przez wywołanie clear. Po trzecie, wszystkie zgromadzone dane będą ostatecznie musiały zostać zniszczone.

Powiązane problemy