std::vector versus std:: array in C++

Jaka jest różnica między std::vector a std::array W C++? Kiedy należy preferować jedno od drugiego? Jakie są plusy i minusy każdego z nich? Wszystko, co robię w podręczniku, to lista, jak są takie same.

Author: Martin G, 2010-12-13

6 answers

std::vector jest klasą szablonów, która hermetyzuje tablicę dynamiczną1, przechowywany w stercie, która rośnie i kurczy się automatycznie, jeśli elementy są dodawane lub usuwane. Zapewnia wszystkie haki (begin(), end(), Iteratory, etc), które sprawiają, że działa dobrze z resztą STL. Posiada również kilka przydatnych metod, które pozwalają wykonywać operacje, które na normalnej tablicy byłyby uciążliwe, jak np. wstawianie elementów w środku wektora (obsługuje całą pracę przesuwania następujących elementy za kulisami).

Ponieważ przechowuje elementy w pamięci przydzielonej na stercie, ma pewne narzuty w odniesieniu do tablic statycznych.

std::array jest klasą szablonową, która hermetyzuje tablicę wielkości statycznej, przechowywaną wewnątrz samego obiektu, co oznacza, że jeśli utworzysz instancję klasy na stosie, sama tablica będzie na stosie. Jego rozmiar musi być znany w czasie kompilacji (jest przekazywany jako parametr szablonu) i nie może rosnąć ani kurczyć.

It ' s more ograniczone niż std::vector, ale często jest bardziej wydajne, szczególnie w przypadku małych rozmiarów, ponieważ w praktyce jest to głównie lekka owijka wokół tablicy w stylu C. Jest to jednak bezpieczniejsze, ponieważ domyślna konwersja na wskaźnik jest wyłączona i zapewnia wiele funkcji związanych z STL std::vector i innych kontenerów, dzięki czemu można go łatwo używać z algorytmami STL & co. W każdym razie, dla samego ograniczenia stałego rozmiaru jest znacznie mniej elastyczny niż std::vector.

Na wprowadzenie do std::array, zajrzyj do tego artykułu; aby szybko zapoznać się z std::vectori możliwymi na nim operacjami, możesz zajrzeć do jego dokumentacji.


  1. właściwie myślę, że w standardzie są one opisane w kategoriach maksymalnej złożoności różnych operacji (np. dostęp losowy w stałym czasie, iteracja wszystkich elementów w czasie liniowym, dodawanie i usuwanie elementów na końcu w stałym czasie amortyzowanym itp.), ale AFAIK nie ma innej metody spełnienia takich wymagań niż użycie tablicy dynamicznej. jak stwierdził @Lucretiel, standard w rzeczywistości wymaga, aby elementy były przechowywane równolegle, więc jest to dynamiczna tablica, przechowywana tam, gdzie skojarzony alokator ją umieszcza.
 256
Author: Matteo Italia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-21 11:56:24

Użycie klasy std::vector<T>:

  • ...jest tak samo szybkie jak używanie wbudowanych tablic, zakładając, że robisz tylko te rzeczy, na które pozwalają wbudowane tablice (odczyt i zapis do istniejących elementów).

  • ...automatycznie zmienia rozmiar po włożeniu nowych elementów.

  • ...umożliwia wstawianie nowych elementów na początku lub w środku wektora, automatycznie "przesuwając" resztę elementów " w górę"( czy to ma sens?). Pozwala również na usuwanie elementów w dowolnym miejscu std::vector, automatycznie przesuwając resztę elementów w dół.

  • ...pozwala na wykonywanie odczytu sprawdzonego zakresu za pomocą metody at() (zawsze możesz użyć indeksatorów [], Jeśli nie chcesz, aby to sprawdzanie było wykonywane).

Istnieją dwa trzy główne zastrzeżenia do użycia std::vector<T>:

  1. Nie masz niezawodnego dostępu do podstawowego wskaźnika, który Może być problemem, jeśli masz do czynienia z funkcjami innych firm, które wymagają adresu tablicy.

  2. Klasa jest głupia. Jest zaimplementowany jako skondensowane pole bitowe, a nie jako tablica. Unikaj go, jeśli chcesz tablicę bool s!

  3. W trakcie użycia, std::vector<T> s będą nieco większe niż tablica C++ z taką samą liczbą elementów. Dzieje się tak dlatego, że muszą śledzić niewielką ilość innych informacji, takich jak ich obecny rozmiar i ponieważ ilekroć std::vector<T>s zmieniają Rozmiar, rezerwują więcej miejsca niż potrzebują. Ma to zapobiec konieczności zmiany rozmiaru za każdym razem, gdy wstawiany jest nowy element. To zachowanie można zmienić poprzez podanie niestandardowego allocator, ale nigdy nie czułem takiej potrzeby!


Edit: po przeczytaniu odpowiedzi Zuda na pytanie poczułem, że powinienem dodać to:

Klasa std::array<T> nie jest taka sama jak tablica C++. std::array<T> jest bardzo cienką owijką wokół tablic C++, której głównym celem jest ukrywanie wskaźnika przed użytkownikiem klasy (w C++ tablice są domyślnie rzucane jako wskaźniki, często do niepokojącego efektu). Klasa std::array<T> przechowuje również swój rozmiar (Długość), co może być bardzo przydatne.

 14
Author: ClosureCowboy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-12 23:32:34

Aby podkreślić punkt wykonany przez @ MatteoItalia, różnica wydajności jest tam, gdzie dane są przechowywane. Pamięć sterty (wymagana z vector) wymaga wywołania systemu w celu przydzielenia pamięci i może to być kosztowne, jeśli liczysz cykle. Pamięć stosu (możliwa dla array) jest praktycznie "zerowa" pod względem czasu, ponieważ pamięć jest przydzielana przez dostosowanie wskaźnika stosu i odbywa się to tylko raz przy wejściu do funkcji. Stos pozwala również uniknąć fragmentacji pamięci. Być oczywiście, std::array nie zawsze będzie na stosie; zależy to od tego, gdzie go przydzielisz, ale i tak będzie to wymagało o jeden mniej alokacji pamięci ze sterty w porównaniu do vector. Jeśli masz

  • mała "tablica" (powiedzmy poniżej 100 elementów) - (typowy stos ma około 8MB, więc nie przydzielaj więcej niż kilka KB na stosie lub mniej, jeśli twój kod jest rekurencyjny)
  • Rozmiar zostanie ustalony
  • lifetime znajduje się w zakresie funkcji (lub jest wartością członka o tym samym czasie życia co rodzic class)
  • liczysz cykle,

Definitywnie użyj std::array nad wektorem. Jeśli którykolwiek z tych wymogów nie jest prawdziwy, należy użyć std::vector.

 11
Author: Mark Lakata,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-29 18:21:51

Jeśli rozważasz użycie tablic wielowymiarowych, to istnieje jedna dodatkowa różnica między STD:: array i std:: vector. Wielowymiarowa tablica std:: będzie miała elementy spakowane w pamięci we wszystkich wymiarach, tak jak tablica w stylu C. Wielowymiarowe std:: vector nie będzie pakowane we wszystkich wymiarach.

Biorąc pod uwagę następujące deklaracje:

int cConc[3][5];
std::array<std::array<int, 5>, 3> aConc;
int **ptrConc;      // initialized to [3][5] via new and destructed via delete
std::vector<std::vector<int>> vConc;    // initialized to [3][5]

Wskaźnik do pierwszego elementu tablicy w stylu C (cConc) lub std:: array (aConc) może być iterowany przez cała tablica przez dodanie 1 do każdego poprzedzającego elementu. Są szczelnie zapakowane.

Wskaźnik do pierwszego elementu w tablicy wektorowej (vConc) lub tablicy wskaźników (ptrConc) może być iteracyjny tylko przez pierwszych 5 (w tym przypadku) elementów, a następnie jest 12 bajtów (w moim systemie) napowietrznych dla następnego wektora.

Oznacza to, że tablica std:: vector> zainicjalizowana jako tablica [3][1000] będzie znacznie mniejsza w pamięci niż tablica zainicjalizowana jako tablica [1000] [3] i obie będą większa w pamięci niż tablica STD: przydzielona w obie strony.

Oznacza to również, że nie można po prostu przekazać wielowymiarowej tablicy wektorowej (lub wskaźnika) do, powiedzmy, OpenGL bez uwzględniania napowietrzności pamięci, ale można naiwnie przekazać wielowymiarową tablicę std::do openGL i mieć to wypracowane.

 8
Author: psimpson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-02 18:01:37

Jedną z zalet wektorów nad tablicami jest to, że można znaleźć Obecny Rozmiar wektor vector_name.size () .

Jak można sobie wyobrazić, może to być bardzo przydatne w różnych sytuacjach, w których można łatwo pobrać liczbę elementów z array_list.

 -12
Author: tech_boy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-21 09:46:06

Wektor jest klasą kontenera, podczas gdy tablica jest przydzieloną pamięcią.

 -14
Author: Saif al Harthi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-12 22:58:17