200 likes | 331 Views
C++ wykład 13,14,15 (16/23/30.05.2012). STL. STL. STL (ang. Standard Template Library) to standardowa biblioteka wzorców w C++. Wszystkie składniki STL są wzorcami. STL jest rdzeniem biblioteki standardowej C++.
E N D
STL • STL (ang. Standard Template Library) to standardowa biblioteka wzorców w C++. • Wszystkie składniki STL są wzorcami. • STL jest rdzeniem biblioteki standardowej C++. • Wszystkie identyfikatory w bibliotece standardowej C++ zdefiniowane są w przestrzeni nazw std. • Zaleta STL – mnóstwo gotowych szablonów klas pozwalających programować na wyższym poziomie abstrakcji. • Wada STL – brak oczywistości (koniecznie czytaj dokumentację)
STL • Biblioteka STL składa się z kilku modułów: • kontenery (sekwencyjne, asocjacyjne), • iteratory (dwukierunkowe, z dostępem swobodnym), • algorytmy, • a także funktory (obiekty funkcyjne, predykaty), łańcuchy, strumienie.
Pary • Szablon struktury pair<> (zdefiniowany w <utility>) umożliwia potraktowanie dwóch wartości jako pojedynczego elementu. • Para posiada dwa pola: first i second. • Para posiada konstruktor dwuargumentowy oraz domyślny i kopiujący. • Pary można porównywać (operatory == i <). • Istnieje szablon funkcji make_pair() do tworzenia pary. • Przykłady:void f (std::pair<int, const char *>);void g (std::pair<const int, std::string>);…std::pair<int, const char *> p(44,”witaj”);f(p); // wywołuje domyślny konstruktor kopiującyg(p); // wywołuje konstruktor wzorcowyg(std::make_pair(44,”witaj”)); // przekazuje dwie // wartości jako parę z wykorzystaniem konwersji // typów • Pary są wykorzystywane w kontenerach map i multimap.
Ograniczenia liczbowe • Typy numeryczne posiadają ograniczenia zależne od platformy i są zdefiniowane w szablonie numeric_limits<> (zdefiniowany w <limits>, stałe preprocesora są nadal dostępne w <climits> i <cfloat>). • Wybrane składowe statyczne szablonu numeric_limits<>: is_signed, is_integer, is_exact, is_bounded, is_modulo, has_infinity, has_quiet_NaN, min(), max(), epsilon(). • Przykłady:numeric_limits<char>::is_signed;numeric_limits<short>::is_modulo;numeric_limits<long>::max();numeric_limits<float>::min();numeric_limits<double>::epsilon();
Minimum i maksimum • Obliczanie wartości minimalnej oraz maksymalnej:template <class T>inline const T& min (const T &a, const T &b) { return b<a ? b : a; }template <class T>inline const T& max (const T &a, const T &b) { return a<b ? b : a; } • Istnieją też wersje tych szablonów z komparatorami (funkcja lub obiekt funkcyjny):template <class T, class C>inline const T& min (const T &a, const T &b, C comp) { return comp(b,a) ? b : a; }template <class T>inline const T& max (const T &a, const T &b, C comp) { return comp(a,b) ? b : a; }
Minimum i maksimum • Przykład 1:bool int_ptr_less (int *p, int *q) { return *p<*q; }…int x = 33, y = 44;int *px = &x, *py = &y;int *pmax = std::max(px,py,int_ptr_less); • Przykład 2:int i;long l;…l = max(i,l); // BŁĄD // niezgodne typy argumentówl = std::max<long>(i,l); // OK
Zamiana wartości • Zamiana dwóch wartości:template <class T>inline void swap (T &a, T &b) { T tmp(a); a = b; b = tmp; } • Przykład:int x = 33, y = 44;…std::swap(x,y);
Operatory porównywania • Cztery funkcje szablonowe (zdefiniowane w <utility>) na podstawie operatorów == i < definiują operatory porównań !=, <=, >= i >. • Funkcje te są umieszczone w przestrzeni nazw std::rel_ops. • Przykład:class X { …public: bool operator== (const X &x) const throw(); bool operator< (const X &x) const throw(); …};…void foo () { using namespace std::rel_ops; X x1, x2; … if (x1!=x2) { … } …}
Kontenery • Kontenery służą do przechowywania i zarządzania kolekcjami danych. • Rodzaje kontenerów: • Kontenery sekwencyjne, gdzie każdy element ma określoną pozycję. Na przykład: vector, deque, list. • Kontenery uporządkowane (w tym asocjacyjne), gdzie pozycja elementu zależy od jego wartości. Na przykład: set, multiset, map, multimap.
Elementy kontenerów • Elementy kontenerów muszą spełniać wymagania podstawowe: • element musi być kopiowalny (konstruktor kopiujący), • element musi być przypisywalny (przypisanie kopiujące), • element musi być zniszczalny (publiczny destruktor). • W pewnych sytuacjach elementy kontenerów muszą spełniać wymagania dodatkowe: • konstruktor domyślny (utworzenie niepustego kontenera), • operator porównywania == (wyszukiwanie), • operator porównywania < (kryterium sortowania).
Semantyka wartości a semantyka referencji • Kontenery STL realizują semantykę wartości: tworzą wewnętrzne kopie swoich elementów oraz zwracają kopie tych elementów. • Semantykę referencji można zaimplementować samodzielnie za pomocą inteligentnych wskaźników – wskaźniki te mają umożliwiać zliczanie referencji dla obiektów, do których odnoszą się wskaźniki.
Kontenery sekwencyjne– wektory • Wektor vector<> (zdefiniowany w <vector>) przechowuje swoje elementy w tablicy dynamicznej. • Uzyskujemy szybki dostęp do każdego elementu za pomocą indeksowania. • Dołączanie i usuwanie elementów na końcu wektora jest bardzo szybkie, ale wstawienie lub usunięcie elementu ze środka zabiera więcej czasu. • Przykład:vector<int> coll;…for (int i=1; i<=6; ++i) coll.push_back(i);…for (int i=0; i<coll.size(); ++i) cout << coll[i] << ’ ’;cout << endl;
Kontenery sekwencyjne– kolejki o dwóch końcach • Kolejka o dwóch końcach deque<> (zdefiniowana w <deque>) przechowuje swoje elementy w tablicy dynamicznej, która może rosnąć w dwie strony. • Uzyskujemy szybki dostęp do każdego elementu za pomocą indeksowania. • Dołączanie i usuwanie elementów na końcu i na początku kolejki jest bardzo szybkie, ale wstawienie lub usunięcie elementu ze środka zabiera więcej czasu. • Przykład:deque<float> coll;…for (int i=1; i<=6; ++i) coll.push_front(i*1.234);…for (int i=0; i<coll.size(); ++i) cout << coll[i] << ’ ’;cout << endl;
Kontenery sekwencyjne– listy • Lista list<> (zdefiniowana w <list>) przechowuje swoje elementy w liście dwukierunkowej. • W listach nie ma swobodnego dostępu do elementów kolekcji. • Dołączanie i usuwanie elementów na końcu i na początku listy jest bardzo szybkie, ale dostanie się do elementu ze środka zabiera dużo czasu. • Przykład:list<char> coll;…for (char c=’a’; c<=’z’; ++c) coll.push_back(c);…while (!coll.empty()) { cout << coll.front() << ’ ’; coll.pop_front(); }cout << endl;
Kontenery sekwencyjne– łańcuchy i tablice • Obiektów klas łańcuchowych, czyli basic_string<>, string i wstring, można używać jak kontenerów sekwencyjnych. Są one podobne w zachowaniu do wektorów. • Innym rodzajem kontenera może być tablica. Nie jest to klasa i nie ma żadnych metod ale konstrukcja STL umożliwia uruchamianie na tablicach różnych algorytmów (tak jak na kontenerach).
Kontenery uporządkowane • Kontenery uporządkowane wykonują automatycznie sortowanie swoich elementów. • Asocjacyjne kontenery uporządkowane przechowują pary klucz-wartość (odpowiednio first i second) i sortowanie następuje po kluczach. • Domyślnie elementy lub klucze są porządkowane przy pomocy operatora <. • Kontenery uporządkowane są implementowane w postaci zrównoważonych drzew BST (drzewa czerwono-czarne). • Wszystkie kontenery uporządkowane posiadają domyślny parametr wzorca służący sortowaniu (domyślnym jest operator <). • Rodzaje kontenerów: zbiory set<>, wielozbiory multiset<>, mapy map<> i multimapy multimap<>.
Adaptatory kontenerów • Adaptatory kontenerów to kontenery wykorzystujące ogólną strukturę innych kontenerów do realizacji pewnych specyficznych potrzeb. • Adaptatorami kontenerów są stosy stack<>, kolejki queue<> i kolejki priorytetowe priority_queue<>.
Iteratory • Iterator to specjalny obiekt, który potafi iterować po elementach kolekcji. • Iterator ma zaimplementowaną semantykę wskaźnika – posiada operator wyłuskania elementu *, operatory przechodzenia do elementówsąsiednich ++ i -- oraz operatory porównywania pozycji == i !=. • Wszystkie kontenery udostępniają funkcje tworzące iteratory do nawigowania po ich elementach – funkcja begin() zwraca iterator wskazujący na pozycję z pierwszym elementem w kolekcji a funkcja end() zwraca iterator wskazujący pozycję za ostatnim elementem. • Każdy kontener definiuje dwa typy iteratorów – kontener::iterator przeznaczony do iterowania po elementach z możliwością odczytu i zapisu oraz kontener::const_iterator przeznaczony do iterowania po elementach tylko z możliwością odczytu.
Iteratory • Przykład 1:list<char> coll;…list<char>::const_iterator pos;for (pos=coll.begin(); pos!=coll.end(); ++pos) cout << *pos << ’ ’;cout << endl; • Przykład 2:list<char> coll;…list<char>::iterator pos;for (pos=coll.begin(); pos!=coll.end(); ++pos) *pos = toupper(*pos);