2013-09-24 18 views
11

przypuśćmy, że chcemy stanowią dwuwymiarową matrycę int jako wektor wektorów:wektora wektorów rezerwa

std::vector<std::vector<int> > myVec; 

wewnętrzny wymiar jest stała, np 5 i zewnętrzny wymiar jest mniejszy niż lub równa się N. Aby zminimalizować ponowny przydział, chciałbym zarezerwować miejsce:

myVec.reserve(N); 

Jakiego rozmiaru przyjmuje się wewnętrzny wektor? Czy ta czysta implementacja jest zależna? W jaki sposób wpływa to na przestrzenną lokalizację danych? Ponieważ wewnętrzny wymiar jest stałą, czy istnieje sposób, aby kompilator mógł użyć tego stałego rozmiaru? Jak zmieniają się te odpowiedzi, jeśli zmienia się rozmiar wektora wewnętrznego?

+1

wektor wektorów nie jest szczególnie dobrym sposobem reprezentowania prostokątnej matrycy. Jest bardziej przydatny w przypadku postrzępionych tablic, gdzie każdy wiersz ma inną liczbę kolumn. –

Odpowiedz

5

Ponieważ wymiar wewnętrzny jest stała, myślę, że chcesz

std::vector< std::array<int, 5> > vecs; 
vecs.reserve(N); 

to daje zdefiniowanej przez ciągłą magazyn, który jest optymalny dla wydajności.

+1

To działa tylko w C++ 11, proszę wspomnieć o tym. –

+0

@Samer: To bzdura, 'tablica' nie wymaga żadnych funkcji C++ 11 i jest dostępna jako' std :: tr1 :: array' od 2007 i 'boost :: array' jeszcze wcześniej. –

3

Wielkość wektorów wewnętrznych jest całkowicie nieistotna przy zmianie rozmiaru wektora zewnętrznego. Nie ma gwarancji lokalizacji dla twojego pakietu wektorów, gwarancja lokalizacji (tj. Ciągły blok w pamięci) istnieje tylko dla jednego wektora.

Należy pamiętać, że sam obiekt wektorowy ma stałą wartość sizeof, jego rzeczywiste dane są zwykle przydzielane dynamicznie. Wektor zewnętrzny, do pierwszego przybliżenia, jest ciągłym blokiem N 'wskaźników do wektorów wewnętrznych. Wywołanie reserve nie rezerwuje pamięci dla możliwych elementów wektorów wewnętrznych, ale tylko dla samych wewnętrznych obiektów wektorowych (tj. Ich danych księgowych i ich wskaźników do ich dynamicznie przydzielonych bloków danych).

1

Wektory wewnętrzne są inicjowane za pomocą domyślnego konstruktora. Więc jeśli piszesz:

vector<vector<int> > vecs; 
vecs.reserve(10); 

Jest to równoznaczne z wywołaniem constuctor z vector<int> lub vector<int>() dla każdego elementu. Co oznacza, że ​​będziesz miał wektor wielkości zerowej. Pamiętaj jednak, że nie możesz ich użyć, chyba że zmienisz (nie zarezerwujesz) swoje wektory.

Pamiętaj też, że czasami może być bardziej efektywna zmiana rozmiaru przy początkowym rozmiarze, którego potrzebujesz. Więc to jest przydatne do zrobienia czegoś jak

vector<vector<int> > vecs(3,vector<int>(5)); 

To stworzy wektor o rozmiarze 3, a każdy element będzie zawierać wektor wielkości 5.

Należy również pamiętać, że może to być bardziej efektywne w użyciu deque zamiast wektora, jeśli często zmieniasz rozmiar swoich wektorów. Są łatwe w użyciu (jako wektory) i nie trzeba rezerwować, ponieważ elementy nie sąsiadują z pamięcią.

+0

Dwuwymiarowa macierz jest prawdopodobnie używana do dostępu losowego, którego 'deque' nie może zrobić wydajnie. –