C++/Vector: Różnice pomiędzy wersjami

Usunięta treść Dodana treść
Lethern (dyskusja | edycje)
przebudowa, opis zorientowany bardziej na C++ niż styl tablic z C, usunięcie treści powielającej temat iteratorów, dodatkowy akapit
Linia 1:
== Vector ==
 
Klasa <tt>vector</tt> reprezentuje obudowaną, zwykłą tablicę znaną z C, wyposażoną w kilka dodatkowych mechanizmów. Elementy wektora mogą być dowolnego typu.
Klasa vector reprezentuje tablicę standardową. Dzięki niej możemy tworzyć tablice dowolnych typów. Aby łatwiej sobie przyswoić klasę vector napiszę ten sam przykład najpierw przy użyciu zwykłej tablicy a potem klasy vector.
 
Obiekt <tt>vector</tt> ma kilka odmian konstruktorów. Z reguły będziemy tworzyć wektor pusty.
Zwykła tablica:
<source lang="cpp">
 
vector < typ_elemetow > nazwa_tablicy;
string tab[10];
</source>
tab[0] = "a";
for (short i = 1; i < 10; i++)
tab[i] = "dluzsze napisy";
 
To samo z wykorzystaniem klasy vector. Aby to skompilować musimy dołączyć plik nagłówkowy <vector>:
 
vector< string > tab(10);
tab[0] = "a";
for (vector< string >::size_type i = 1; i < tab.size(); ++i)
tab[i] = "dluzsze napisy";
 
Składowa vector<T>::size_type jest aliasem do typu właściwego dla indeksowania elementów wektora - gwarantuje, że typ będzie miał wystarczający zakres, żeby obsłużyć całą długość wektora. Innymi słowy - rozmiar wektora (vector<T>::size()) jest właśnie typu size_type. Użycie size() zamiast stałej gwarantuje nam, że zmieniając rozmiar bufora zawsze przeiterujemy go do końca.
 
Obiekt vector ma kilka odmian konstruktorów. Możemy stworzyć wektor pusty, a później dodawać do niego elementy. Wtedy wektor sam będzie sie powiększał. Nie musimy znać rozmiaru podczas tworzenia obiektu.
 
vector < typ_elemetow > nazwa_tablicy;
 
Możemy też podać wielkość, co wcale nas nie ogranicza do tej wielkości. Jeżeli zabraknie miejsca obiekt sam sie powiększy.
 
Możemy też podać wielkość, co wcale nas nie ogranicza do tej wielkości. JeżeliMoże zabraknieto miejscabyć obiektzabieg sam sie powiększyoptymalizacyjny.
<source lang="cpp">
vector < int > tab(20);
</source>
 
MyślęDodatkowo żeistnieje możekonstruktor się przydać jeszcze wersja konstruktora która podajeprzyjmujący liczbę elementów ioraz wartość, jaką ma mieć każdy z nich.
<source lang="cpp">
 
vector < string > tablica( 20, "przykladowy tekst" dla kazdego elementu");
</source>
 
Ta tablica będzie miała dwadzieścia elementów, z czego wszystkie mają wartość: "przykladowy tekst dla kazdego elementu".
Jeżeli podamy ilość elementów wtedy należy do nich odwoływać sie za pomocą operatora indeksowego [], lub czuwającą żeby nie wyjść poza zakres elementów metodą at(). Natomiast jeżeli nie podamy ilości wtedy trzeba najpierw utworzyć każdy kolejny element, czynimy to metodą push_back(). Ta metoda dodaje nowy element na koniec tablicy. Po dodaniu nowych elementów możemy sie do nich odwoływać indeksowo []. Możemy też sprawdzić ile obecnie jest elementów metodą size(), a metoda empty() powie nam czy przypadkiem wektor nie jest pusty.
Dalsze wnikanie w możliwości klasy vector wymaga poznania iteratorów – inaczej wskaźniki. Jak wiemy do poruszania sie po elementach tablicy takich jak int a[10] można używać wskaźnika jakim jest a. Tak samo operacje na obiektach wektora można dokonać używając iteratorów i algorytmów uogólnionych. Rzućmy wiec okiem na te iteratory.
Deklaracja iteratora wygląda podobnie do deklaracji wektora. Zadeklarujemy wektor 10 elementów typu string i dwa iteratory do niego. Pierwszy będzie wskazywał na pierwszy element, a drugi na pierwszy po ostatnim. Do uzyskania takich iteratorów służą metody begin() i end(), które zwracają iterator odpowiednio do pierwszego i następnego po ostatnim (nie ostatniego) elementu.
 
=== Dodawanie elementów ===
vector<string> tabStr(10,"0");
Jeżeli podamy ilośćDodawanie elementów wtedyumożliwia należy do nich odwoływać sie za pomocą operatora indeksowego [], lub czuwającą żeby nie wyjść poza zakres elementów metodą at(). Natomiast jeżeli nie podamy ilości wtedy trzeba najpierw utworzyć każdy kolejny element, czynimy to metodąmetoda <tt>push_back()</tt>. TaDodaje metoda dodajeona nowy element na koniec tablicy. Po dodaniu nowych elementów możemy siesię do nich odwoływać indeksowo [] lub metodą <tt>at()</tt>. Możemy też sprawdzić ile obecnie jest elementów metodą <tt>size()</tt>, a metoda <tt>empty()</tt> powie nam czy przypadkiem wektor nie jest pusty.
vector<string>::iterator iter1;
vector<string>::iterator iter2;
iter1 = tabStr.begin();
iter2 = tabStr.end();
 
Jak wiemy, do poruszania się po elementach zwykłej tablicy takiej jak <tt>int a[10]</tt> można używać wskaźnika. Podobnie, operacje na obiekcie vector można dokonać używając iteratorów działających podobnie jak wskaźniki. Więcej o iteratorach znajduje się w dalszych rozdziałach.
Mając takie iteratory możemy sie nimi posługiwać na wzór standardowych wskaźników. Można go wyłuskać, używać operatorów arytmetycznych ++, -- i logicznych. Poniższy program to ilustruje.
 
=== Jak działa powiększanie się tablicy vector? ===
#include <string>
Poniższy akapit dotyczy szczegółów technicznych, jeśli nie jesteś nimi zainteresowany, możesz go pominąć.
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char *argv[])
{
vector<string> tabStr(10,"0");
vector<string>::iterator iter1;
vector<string>::iterator iter2;
iter1 = tabStr.begin();
iter2 = tabStr.end();
for (int a = 0; iter1 != iter2; ++iter1, ++a )
{
if (a % 2 == 0)
*iter1 = "1";
cout << *iter1 << endl;
}
cin.get();
return 0;
}
 
Metoda <tt>push_back()</tt> dodając nowy element do tablicy, dba o to, aby tablica była odpowiedniego rozmiaru. Za każdym razem, gdy brakuje miejsca, tablica jest powiększana - rezerwowana jest nowa, większa przestrzeń, stare elementy są kopiowane, aby do większej tablicy móc dodać dany element. Z reguły rezerwowana jest pamięć dwa razy większa od poprzedniej. Może to doprowadzić do sytuacji, kiedy zarezerwowana pamięć jest prawie dwa razy większa niż ilość elementów znajdujących się w niej!
Wynik działania:
1
0
1
0
1
0
1
0
1
0
 
Jeśli zależy nam na szybkości działania, powinniśmy zarezerwować przy pomocy odpowiedniego konstruktora pamięć na pewną ilość elementów. Przykładowo, jeśli wiemy że w tablicy będzie około 50 elementów, możemy konstruować wektor o wielkości 50, dzięki czemu unikniemy kilku kopiowań całej tablicy podczas dodawania elementów. Warto też szukać złotego środka, aby przypadkiem nie marnować pamięci. Na przykład, aby nie stworzyć wektora o rozmiarze 100, jeśli dodane do niego będą tylko 2 elementy.
Ale iteratory są o wiele bardziej skomplikowane niż tu zostało to przedstawione. Jest pięć rodzajów iteratorów ogólnych, bo każda klasa taka jak vector ma w sobie zdefiniowany iterator. Iteratory będziemy wykorzystywać prawie w każdym kontenerze (struktura do przechowywania danych) jakim jest np. vector.
Teraz, kiedy już wiemy, co to są iteratory, możemy przejść do metod klasy vector i algorytmów uogólnionych, które działają najlepiej na tych iteratorach. Klasa vector nie ma sama w sobie zbyt wiele metod do ciekawych operacji, ale tego braku uzupełnieniem jest zbiór algorytmów uogólnionych, o których będę pisał później.
<br\ >
 
==Metody==
Lista metod klasy vector. (gdzieUżyte słowo <tt>iterator</tt> tozastępuje poprawne <tt>vector<T>::iterator</tt>, -podmienione podmianazostało dla zwiększenia czytelności):.
 
{| class="wikitable"