O ile zrozumiałem standard (chociaż właściwie nie mogłem nazwać referencji), instancjacja kontenera i alokacja pamięci zostały celowo rozdzielone nie bez powodu. Dlatego masz różne, oddzielne wezwania
constructor
aby stworzyć sam kontener
reserve()
aby wstępnie przydzielić odpowiednio duży blok pamięci, aby pomieścić co najmniej (!) daną liczbę obiektów
I to ma sens. Jedynym prawem do istnienia reserve()
jest danie ci możliwości kodowania wokół potencjalnie kosztownych realokacji podczas wzrostu wektora. Aby być użytecznym, musisz znać liczbę obiektów do przechowywania lub przynajmniej umieć dokonać świadomego przypuszczenia. Jeśli to nie jest podane, lepiej trzymaj się z daleka, reserve()
ponieważ po prostu zmienisz realokację na zmarnowaną pamięć.
Więc łącząc to wszystko razem:
- Standard celowo nie określa konstruktora, który pozwala wstępnie zaalokować blok pamięci dla określonej liczby obiektów (co byłoby przynajmniej bardziej pożądane niż przydzielenie konkretnego, ustalonego „czegoś” pod maską).
- Alokacja nie powinna być niejawna. Tak więc, aby wstępnie przydzielić blok, musisz wykonać osobne wywołanie,
reserve()
a to nie musi znajdować się w tym samym miejscu budowy (może / powinno być oczywiście później, po uzyskaniu informacji o wymaganym rozmiarze do pomieszczenia)
- Tak więc, gdyby wektor zawsze wstępnie przydzielał blok pamięci o zdefiniowanym przez implementację rozmiarze, udaremniłoby to zamierzone zadanie
reserve()
, prawda?
- Jaka byłaby zaleta wstępnego przydzielania bloku, jeśli STL w naturalny sposób nie może znać zamierzonego celu i oczekiwanego rozmiaru wektora? Będzie to raczej bezsensowne, jeśli nie przyniesie odwrotnych skutków.
- Zamiast tego właściwym rozwiązaniem jest przydzielenie i zaimplementowanie określonego bloku za pomocą pierwszego
push_back()
- jeśli nie został on wcześniej wyraźnie przydzielony przez reserve()
.
- W przypadku konieczności ponownej alokacji zwiększenie rozmiaru bloku jest również zależne od implementacji. Implementacje wektorów, o których wiem, zaczynają się od wykładniczego wzrostu rozmiaru, ale ograniczają szybkość przyrostu do pewnego maksimum, aby uniknąć marnowania ogromnej ilości pamięci, a nawet jej przepalenia.
Wszystko to w pełni działa i przynosi korzyści tylko wtedy, gdy nie jest zakłócane przez konstruktora alokującego. Masz rozsądne wartości domyślne dla typowych scenariuszy, które można zastąpić na żądanie przez reserve()
(i shrink_to_fit()
). Tak więc, nawet jeśli standard nie stwierdza tego wprost, jestem całkiem pewien, że założenie, że nowo skonstruowany wektor nie jest wstępnie przydzielony, jest całkiem bezpiecznym zakładem dla wszystkich obecnych implementacji.