Wstępnie przydzielam trochę pamięci do mojej vector
zmiennej składowej. Poniższy kod to minimalna część
class A {
vector<string> t_Names;
public:
A () : t_Names(1000) {}
};
Teraz w pewnym momencie, jeśli t_Names.size()
równa się 1000
. Zamierzam zwiększyć rozmiar o 100
. Następnie, jeśli osiągnie 1100
, ponownie zwiększ o 100
i tak dalej.
Moje pytanie brzmi, co wybrać między vector::resize()
a vector::reserve()
. Czy jest lepszy wybór w takim scenariuszu?
Edycja : mam dokładne oszacowanie dla t_Names
. Szacuję, że jest ok 700
do 800
. Jednak w niektórych (rzadkich) sytuacjach może wzrosnąć bardziej niż 1000
.
std::vector
.Odpowiedzi:
Te dwie funkcje robią bardzo różne rzeczy!
resize()
Metoda (i przechodzącej argumentu konstruktora jest równoważna) będzie wstawić lub usunąć odpowiednią liczbę elementów do wektora, aby podane wielkości (ma opcjonalny drugi argument do określenia ich wartości). Wpłynie to nasize()
, iteracja przejdzie przez wszystkie te elementy, push_back wstawi po nich i możesz uzyskać do nich bezpośredni dostęp za pomocąoperator[]
.reserve()
Metoda przydziela tylko pamięć, ale pozostawia niezainicjowanymi. Ma to tylko wpływcapacity()
, alesize()
pozostanie niezmienione. Nie ma wartości dla obiektów, ponieważ nic nie jest dodawane do wektora. Jeśli następnie wstawisz elementy, ponowna alokacja nie nastąpi, ponieważ została wykonana z góry, ale to jedyny efekt.Więc to zależy od tego, czego chcesz. Jeśli chcesz mieć tablicę 1000 domyślnych elementów, użyj
resize()
. Jeśli chcesz mieć tablicę, do której chcesz wstawić 1000 elementów i chcesz uniknąć kilku alokacji, użyjreserve()
.EDYCJA: Komentarz Blastfurnace sprawił, że ponownie przeczytałem pytanie i zdałem sobie sprawę, że w twoim przypadku poprawna odpowiedź to nie przydzielaj wstępnie ręcznie. Po prostu wkładaj elementy na końcu, tak jak potrzebujesz. Wektor będzie automatycznie przydzielić według potrzeb i uczyni go bardziej efektywnie niż ręczny sposób wymienić. Jedynym przypadkiem, w którym
reserve()
ma to sens, jest dość precyzyjne oszacowanie całkowitego rozmiaru, którego potrzebujesz, łatwo dostępne z wyprzedzeniem.EDIT2: Edycja pytania reklamowego: jeśli masz wstępne oszacowanie, to
reserve()
oszacowanie. Jeśli okaże się to niewystarczające, po prostu pozwól wektorowi zrobić swoje.źródło
vector
.x.reserve(x.size() + newdata); vector<int>::iterator special_element = get_special_element(x); for (int i = 0; i < newdata; ++i) { if some_function(i, special_element) x.push_back(i); }
jest dość solidne, jeśli chodzi o rezerwowanie miejsca. Nie mam pojęcia, ile elementów faktycznie zostanie dodanych, ale mam górną granicę. Oczywiście, gdy masz wątpliwości, w przypadku wektorów możesz po prostu użyć indeksów zamiast iteratorów, różnica jest zwykle nieistotna.size()
. „Metoda rezerwacji () tylko przydziela pamięć” - może, ale niecapacity()
musi, przydzielać pamięć w zależności od tego, czy jest już wystarczająca, może również wymagać przeniesienia elementów i zwolnienia ich pierwotnej pamięci. „chcę uniknąć kilku przydziałów” i kopii itp.resize()
nie tylko alokuje pamięć, ale także tworzy tyle instancji, ile żądany rozmiar, który przekazujeszresize()
jako argument. Alereserve()
tylko przydziela pamięć, a nie tworzy instancji. To jest,Wyjście ( demo online ):
Więc
resize()
może nie być pożądane, jeśli nie chcesz domyślnie tworzonych obiektów. Będzie to również powolne. Poza tym, jeślipush_back()
dodasz do niego nowe elementy,size()
wektor będzie się dalej zwiększał poprzez przydzielanie nowej pamięci (co oznacza również przenoszenie istniejących elementów do nowo przydzielonej przestrzeni pamięci). Jeśli użyłeśreserve()
na początku, aby upewnić się, że jest już wystarczająca ilość przydzielonej pamięci,size()
wektor zwiększy się, gdypush_back()
do niego przejdziesz , ale nie przydzieli nowej pamięci ponownie, dopóki nie zabraknie miejsca, które zostało dla niego zarezerwowane .źródło
reserve(N)
możemy używaćoperator []
nieszkodliwie. prawda?reserve
, specyfikacja wymaga, aby alokowała co najmniej tyle, więc niektóre implementacje mogą zaokrąglić w górę do pewnej granicy, a tym samym pokazać większą pojemność niż 1000.v.size()
. Zauważ, żereserve(N)
nie zmienia tosize()
wektora.Z twojego opisu wynika, że chcesz "zarezerwować" przydzieloną przestrzeń pamięci wektorowej t_Names.
Zwróć uwagę, że
resize
zainicjuj nowo przydzielony wektor, w którymreserve
po prostu alokuje, ale nie konstruuje. Dlatego „rezerwa” jest znacznie szybsza niż „zmiana rozmiaru”Możesz zapoznać się z dokumentacją dotyczącą różnicy między zmianą rozmiaru a rezerwą
źródło
zarezerwuj, gdy nie chcesz, aby obiekty były inicjowane po zarezerwowaniu. możesz też chcieć logicznie różnicować i śledzić jego liczbę w porównaniu z liczbą użycia podczas zmiany rozmiaru. więc istnieje różnica w zachowaniu w interfejsie - wektor będzie reprezentował tę samą liczbę elementów po zarezerwowaniu, a po zmianie rozmiaru w scenariuszu będzie o 100 elementów większy.
zależy to całkowicie od twoich celów podczas walki z domyślnym zachowaniem. niektórzy wolą niestandardowe podzielniki - ale naprawdę potrzebujemy lepszego wyobrażenia o tym, co próbujesz rozwiązać w swoim programie, aby dobrze Ci doradzić.
fwiw, wiele implementacji wektorowych po prostu podwoi liczbę przydzielonych elementów, gdy będą musiały wzrosnąć - czy próbujesz zminimalizować maksymalne rozmiary alokacji, czy próbujesz zarezerwować wystarczającą ilość miejsca dla jakiegoś programu bez blokad lub czegoś innego?
źródło
operator[]
ani niczego.