Chciałem poznać zachowanie std::vector::reserve() w następujących sytuacjach:

  1. Załóżmy, że reserve(N) jest wywoływany wielokrotnie jeden po drugim natychmiast. Czy wcześniejszy reserve(N1) zostanie dodany lub nadpisany?
  2. Jeśli wcześniejszy reserve(N1) zostanie nadpisany najnowszym wywołaniem, co się stanie, jeśli najnowszy reserve(Nn) wymaga mniejszej liczby slotów?
  3. Po zadeklarowaniu vector jeśli mamy po prostu push_back() X elementów, a potem dzwonimy reserve(N). Czy już push_back() X elementy zliczone w N ?
  4. Załóżmy, że jeśli vector ma kilka elementów wypchniętych przez X, a teraz, jeśli push_back() 1 element więcej (X+1), wtedy ten obiekt musiałby zostać przeniesionym; ale jeszcze nie wykonaliśmy push_back(). Co się stanie, jeśli zadzwonimy teraz reserve()? Czy obiekt zostanie przeniesiony? od razu ? Jeśli nie, to w jaki sposób zarezerwowane jest miejsce?
9
iammilind 16 luty 2012, 06:55

2 odpowiedzi

Najlepsza odpowiedź

reserve() po prostu upewnia się, że przydzielona pamięć wektora jest co najmniej wystarczająco duża, aby pomieścić liczbę elementów przekazanych jako jego argument. Zatem...

  1. Niezależnie od tego, która maksymalna wartość wszystkich przesłanych danych zostanie przekazana, będzie minimalna efektywna pojemność skutecznie zarezerwowana.
  2. Zobacz # 1.
  3. Tak.
  4. Po wywołaniu reserve() wektor alokuje tyle pamięci, ile jest konieczne do przechowania liczby elementów przekazanych do reserve().

Cytując z aktualnego standardu:

void reserve(size_type n)

Jeśli n jest mniejsze lub równe capacity(), to wywołanie nie przynosi efektu. W przeciwnym razie jest to żądanie przydziału dodatkowej pamięci. Jeśli żądanie powiodło się, wtedy capacity() jest większe lub równe n; w przeciwnym razie capacity() pozostaje bez zmian. W obu przypadkach size() to bez zmian.

12
Amber 16 luty 2012, 22:20

Załóżmy, że reserve(N) jest wywoływany kilka razy jeden po drugim natychmiast. Czy wcześniejszy reserve(N1) zostanie dodany lub nadpisany?

W przeciwieństwie do std::string nie jest możliwe wywołanie reserve() dla std::vector, aby zmniejszyć capacity().Wołanie reserve() z argumentem, który jest mniejszy niż bieżący capacity() to zakaz. Stąd ostatnie wywołanie reserve(), które zwiększa obecną pojemność, będzie dobrze działać.

Jeśli wcześniejszy reserve(N1) zostanie nadpisany ostatnim wywołaniem, to co się stanie, jeśli najnowsze reserve(Nn) wymaga mniejszej liczby slotów?

Wywołanie reserve() z argumentem, który jest mniejszy niż obecny capacity() jest nie-op.

Po zadeklarowaniu wektora, jeśli mamy po prostu push_back() elementy X, a następnie wywołujemy Reserve(N). Czy elementy X push_back() są już liczone w N ?

reserve() po prostu przydziela (rezerwuje) wystarczającą liczbę elementów, więc tak. Zauważ, że po wywołaniu reserve() tylko capacity() wektora jest zmieniane, size() pozostaje niezmienione. Jeśli musisz utworzyć tyle elementów, a nie tylko rezerwować pamięć, powinieneś użyć resize().

Załóżmy, że jeśli wektor ma kilka X wypchniętych elementów, a teraz, jeśli push_back() jeszcze 1 element (X+1), to ten obiekt musiałby zostać przeniesiony; ale jeszcze nie wykonaliśmy push_back(). Co się stanie, jeśli zadzwonimy teraz reserve()? Czy obiekt zostanie natychmiast przeniesiony? Jeśli nie, to w jaki sposób zarezerwowane jest miejsce?

Tak, przeniesienie nastąpi, ale to zależy. Jak wspomniano wcześniej, reserve() przydziela wystarczającą ilość pamięci, aby przechowywać tyle elementów, ile argument został do niego przekazany. Więc jeśli ta liczba elementów jest większa niż ta, którą można zmieścić w bieżącym wektorze capacity(), nastąpi relokacja.

Referencje standardowe:
C++03 23.2.4.2 pojemność wektora [lib.vector.capacity]

void reserve(size_type n);

Skutki: dyrektywa informująca wektor o planowanej zmianie rozmiaru, aby mógł odpowiednio zarządzać przydziałem pamięci. Po reserve() capacity() jest większe lub równe argumentowi rezerwy, jeśli nastąpi realokacja; i równa poprzedniej wartości capacity() w przeciwnym razie. Realokacja ma miejsce w tym momencie wtedy i tylko wtedy, gdy aktualna pojemność jest mniejsza niż argument reserve().

Złożoność: nie zmienia rozmiaru sekwencji i zajmuje maksymalnie liniowy czas jej rozmiaru.

Zrzuty: length_error, jeśli n > max_size().248)

Uwagi: ponowna alokacja unieważnia wszystkie odwołania, wskaźniki i iteratory odnoszące się do elementów w sekwencji. Gwarantuje się, że żadna realokacja nie nastąpi podczas wstawiania, które mają miejsce po wywołaniu reserve() do czasu, gdy wstawienie sprawiłoby, że rozmiar wektora byłby większy niż rozmiar określony w ostatnim wywołaniu reserve() .

4
Community 20 czerwiec 2020, 12:12