2011-10-15 17 views
5

Szybkie pytanie. Powiedzmy, że deklaruję wektor o rozmiarze 20. A potem chcę dodać do niego kilka liczb całkowitych za pomocą funkcji push_back.W języku C++, funkcja wektorowa push_back zwiększy rozmiar pustej tablicy?

vector<int> myVector(20); 
myVector.push_back(5); 
myVector.push_back(14); 

Czy pojemność mojego wektora wynosi teraz 22, czy może nadal wynosi 20? Czy odpowiednio 5 i 14 zostały dodane do indeksów [19] i [20]? A może są to [0] i [1]?

+13

nie wahaj się rzeczywiście spróbować * bardziej *. –

+0

Witamy w StackOverflow, mam nadzieję, że przeczytałeś [FAQ] (http://stackoverflow.com/faq#howtoask). –

Odpowiedz

11

Po tych oświadczeniach jego zdolność jest definiowana przez realizację. (Należy pamiętać, że różni się od jego wielkości.)


vector<int> myVector(20); 

To tworzy wektor wypełniony dwadzieścia 0 jest. Jego rozmiar wynosi dokładnie dwadzieścia, a jego pojemność wynosi co najmniej dwadzieścia. Niezależnie od tego czy jest to dokładnie dwadzieścia, czy nie, definiowane jest wdrożenie; może mieć więcej (prawdopodobnie nie, w praktyce).

myVector.push_back(5); 

Następnie XXI element tablicy ma 5, a wydajność jest ponownie implementacji zdefiniowane. (Jeśli moc była dokładnie dwadzieścia przed, to jest zwiększa się w sposób nieokreślony.)

myVector.push_back(14); 

Podobnie teraz XXII element tablicy ma wartość 14, a pojemność jest realizacja określone.


Jeśli chcesz zarezerwować miejsca, ale nie wstawić elementy, można zrobić to tak:

vector<int> myVector; 
myVector.reserve(20); // capacity is at least twenty, guaranteed not 
         // to reallocate until after twenty elements are pushed 

myVector.push_back(5); // at index zero, capacity at least twenty. 
myVector.push_back(14); // at index one, capacity at least twenty. 
+1

Należy zauważyć, że standard C++ 03 23.2.4/1 wymaga, aby "wektor" był wspierany ** (zamortyzowany) stały czas ** wstawiać i kasować operacje na końcu ", więc w praktyce pojemność zazwyczaj zwiększa się o współczynnik dwa, gdy 'push_back()' potrzebuje więcej miejsca. –

+0

W porządku. Dziękuję Ci. Nie wiedziałem, że wypełni się 20 0. To naprawdę zepsułoby mój program. Nie wiem, dlaczego nie myślałem, żeby nie określać rozmiaru, ponieważ są dynamiczne i tego właśnie potrzebuję. Derp w moim imieniu. – iaacp

1

push_back zwiększa rozmiar std::vector i umieszcza nowe elementy w tylnej części vector (innych pojemnikach też push_front sposób zrobić to samo z przodu, jak również).

Istnieje jednak różnica między rozmiarem i pojemnością urządzenia vector. Rozmiar o rozmiarze odnosi się do tego, ile elementów znajduje się obecnie w modelu ; pojemność odnosi się do całkowitej liczby elementów, które może przechowywać vector bez ponownego przydzielania pamięci. Jest możliwe, aby reserve() pamięci, jeśli wiesz, że masz zamiar dodać kilka elementów i nie chcesz rozwijać fragmentaryczne vector.

+0

OK, więc push_back nie zwiększa pojemności, prawda? O ile ten wektor nie jest już pełen. – iaacp

+0

Prawidłowo, niekoniecznie zwiększa to pojemność. Wspominam tylko o tym, ponieważ 'std :: vector' przechodzi przez trud robienia rozróżnienia, dlatego ważne jest, aby zachować warunki proste, szczególnie podczas czytania dokumentacji dla' std :: vector'. –

1

Ponieważ wektor nie jest pusty ale ma rozmiar 20 (zawiera 20 elementów), a ty push 2 elementy do back, teraz zawiera 22 elementy. Ale nowe elementy nie są umieszczone w indeksach 19 i 20, ale 20 i 21.

Jeśli naprawdę chcesz zarezerwować tylko tyle pamięci, aby wektor mógł pomieścić 20 elementów (bez faktycznego zawierania żadnych elementów), aby zapobiec kosztownym ponownym przydziałom , następnie należy zadzwonić

std::vector<int> myVector; 
myVector.reserve(20); 

w tym przypadku wektor jest jeszcze pusta, ale ma wystarczająco dużo pamięci, aby dodać co najmniej 20 elementów (używając push_back, na przykład), bez konieczności jej ponownego przydzielenia pamięci wewnętrznej. W tym przypadku wektor zawiera tylko 2 elementy, które uzyskałeś push wyd. _back.

+0

Bardzo pomocna, dziękuję. Zasadniczo chcę stworzyć wektor i dodawać elementy tylko do końca. Nie przyszło mi do głowy, że nie muszę początkowo podawać rozmiaru, ponieważ wektory są dynamiczne. Dziękuję Ci! – iaacp

3
  • to liczba elementów w kontenerze wektorów.
  • capacity jest wielkości przydzielonej miejsca
  • push_back skutecznie zwiększa się wielkość wektora jedną, co powoduje przesunięcie wewnętrznego przydzielonej pamięci, jeżeli rozmiar wektor równa pojemności wektora przed wywołaniem.

Więcej informacji: http://www.cplusplus.com/reference/stl/vector/

+0

Idealny. Dziękuję Ci! – iaacp

1

No vector posiada funkcję składową push_back. Inne sekwencje, takie jak deque, mają push_front.

0, 1, 2, ......, końcowe

po dodaniu:

0, 1, 2, ....., final, dodatek ...

Można przypomnieć, że:

capacity() returns the number of elements in the vector sufficient, 
without allocating additional memory. 
This number can be greater or equal to size. 

Oznacza to, że nie można dodać z przodu lub na środku, ponieważ vector specjalizuje się szybki dostęp do elementów przez indeks. Jeśli chcesz dodać z przodu iz tyłu, możesz użyć numeru deque podobnego do vector. Jeśli chcesz dodać do przodu, z powrotem i gdziekolwiek, możesz użyć list. Zauważ, że list nie zapewnia indeksowania takich jak deque i vector.

Jednak zakłada się, że wektor ma większą pojemność niż jego rzeczywisty rozmiar. Po dodaniu do niego elementów nie trzeba przydzielać dodatkowej pamięci. Dzieje się tak tylko wtedy, gdy pojemność jest równa wielkości. W przypadku wielu kompilatorów nowa pojemność będzie dwukrotnie większa od poprzedniej. Po przydzieleniu kopiuje wszystkie elementy w nowej lokalizacji. Takie zachowanie może być jednak kosztowne pod względem pamięci.

1

push_back zwiększy pojemność wektora do co najmniej nowego rozmiaru wektora, ale prawdopodobnie (to znaczy prawdopodobnie) będzie nieco większy.

Ponieważ push_back jest wymagany do uruchomienia w O (1) czasie amortyzacji, każda realokacja będzie równa wielokrotności starej pojemności. W typowej implementacji wielokrotność wynosi 2.

Ale dokładny wzrost wydajności nie jest określony. Jeśli potrzebujesz precyzyjnej kontroli nad pojemnością, użyj reserve.

...

Re czytaniu swoje pytanie, nie jestem pewien, że rozumiesz różnicę pomiędzy wektorem wielkości i pojemności. Rozmiar to liczba elementów. Pojemność to liczba elementów, które wektor może pomieścić bez dokonywania realokacji. Oznacza to, że przed zsynchronizowaniem można uzyskać elementy capacity() - size() o numerach push_back.

W twoim przykładzie, 5 i 14 pojawią się odpowiednio w myVector [20] i myVector [21].

+0

Dobrze. Nie rozumiałem, że wektory nie wymagają zdolności tworzenia ich, to jest punkt - są dynamiczne, prawda? Więc bezsensowne jest dać im początkową pojemność. – iaacp

+0

@iaacp: Nie, to nie jest bezcelowe. Jeśli wiesz z góry, ile rzeczy zamierzasz umieścić w wektorze, ale nie masz odpowiednich rzeczy podczas inicjalizacji wektora, możesz "zarezerwować()" kwotę, aby "wektor" nie musieli dokonać realokacji. –

+0

@iiacp: Nie ma sensu, jeśli zależy Ci na realokacji. Realokacja (a) wymaga czasu i (b) unieważnia odniesienia/wskaźniki do elementów wewnątrz wektora. 'rezerwa' pozwala ustawić zdolność uniknięcia przyszłych przydziałów. Zauważ, że twój przykład ustawia _size_ wektora, a nie _capacity_. Tworzysz wektor 20 niezainicjowanych liczb całkowitych. – Nemo