Upload
maina
View
37
Download
2
Embed Size (px)
DESCRIPTION
STL - Standard Template Library 2 (STL od źródeł , czyli specyfikacja biblioteki). Autor: Błażej Chodarcewicz rainbow.mimuw.edu.pl/~bc189380/STL/. Standard C++ (STL). Organizacja pracująca nad standardem http://anubis.dkuug.dk/jtc1/sc22/wg21/ Wersja Draft 1996 r. - PowerPoint PPT Presentation
Citation preview
STL - Standard Template Library 2(STL od źródeł, czyli specyfikacja biblioteki)
Autor: Błażej Chodarcewiczrainbow.mimuw.edu.pl/~bc189380/STL/
Standard C++ (STL)
Organizacja pracująca nad standardem http://anubis.dkuug.dk/jtc1/sc22/wg21/
Wersja Draft 1996 r.
ISO-IEC 14882 Programming.Language.C++ (1998) ISO/IEC 14882:2003
Jak to działa?
Iteratory
Uogólnienie wstaźników Umożliwiają pracę z kontenerami w ujednolicony sposób Biblioteka formalizuje interfejs, semantykę oraz założenia
złożonościowe Semantyka iteratorów jest uogólnieniem semantyki
wskaźników Wyrażenie *i – wartością jest obiekt pewnej klasy,
enumeracja lub typ wbudowany T, zwany value type of iterator
Wszystkie iteratory i, dla których (*i).m jest zdefiniowane, wspierają także wyrażenie i->m
Dla każdego iteratora typu X, dla którego zdefiniowana jest równość, jest dostępny typ difference type iteratora
Rodzaje iteratorów
input iteratorsoutput iteratorsforward iteratorsbidirectional iteratorsrandom access iterators
Relacje pomiędzy iteratorami
Input Output
Forward
Bidirectional
Random Access
Iteratory zmienialne i niezmienialne
mutable, constant iterators*i jako referencja lub referencja do stałejIteratory stałe nie spełniają wymagań output
iterators
past-the-end value
Dla każdego iteratora istnieje wartość wskazująca na element za ostatnim elementem kolekcji, z którą związany jest iterator
dereferencable values Biblioteka nigdy nie zakłada, że past-the-end value jest
dereferencable
Kilka definicji
Iterator i jest reachable z iteratora i wtw., gdy istnieje skończona sekwencja aplikacji wyrażenia ++i, po której mamy i == j.
Jeśłi i jest reachable z j, to i i j odnoszą się do tej samej kolekcji Range – para iteratorów, które określają początek i koniec obliczeń Range [i, i) – empty range W ogólności range [i, j) odnosi się do elementów struktury
danych zaczynających się od elementu wskazywanego przez i, kończących się na elemencie wskazywanym przez j bez tego elementu
Range [i, j) jest prawidłowe wtw., gdy j jest reachable z i. Aplikacja algorytmu dla nieprawidłowego Range jest nieokreślona
Kilka założeń
Złożoność (zamortyzowana) wszystkich operacji wymaganych dla danej kategorii iteratora jest stała
Na następnych slajdach występują:a, b oznaczają wartości iteratora X, n oznacza wartość typu difference type Distance; u, tmp i m oznaczają identyfikatory, r oznacza wartość X&, t oznacza wartość typu wartości iteratora - T.
Input iterator - wymagania
Operacja Typ Semantyka, założeniaX u(a); X post: u jest kopią a
Destruktor musi być zdefiniowany i dostępny.
u = a; X wynik: u post: u jest kopią a
a == b convertible to bool
== jest relacją równości (w matematycznym sensie) zdefiniowaną na dziedzinie wartości iteratora
a != b convertible to bool
bool(a==b) != bool(a!=b) dla dziedziny ==
*a T pre: a jest dereferenceable
Jeśli a==b i (a,b) należy do dziedziny relacji ==, wtedy *a jest takie samo jak *b.
a->m pre: (*a).m jest dobrze zdefiniowaneSemantyka jest taka sama jak (*a).m
Input iterator – wymagania c.d.
Operacja Typ Semantyka, założenia++r X& pre: r jest dereferenceable
post: r jest dereferenceable lub r jest wartością past-the-end
post: każda kopia poprzednij wartości r nie musi już być ani dereferenceable, ani nawet nie musi
być w dziedzinie ==
(void)r++ taka sama jak (void)++r
*r++ T { T tmp = *r; ++r; return tmp; }
Input iterator – uwagi
a == b nie implikuje ++a == ++bAlgorytmy nigdy nie powinny próbować
przechodzi po tym samym iteratorze dwa razyTyp wartości T nie musi być typem lvalue
(Przykład istream_iterator)
Output iterator - wymagania
Operacja Zwracany typ
Semantyka, założenia
X(a) X a = t jest takie samo jak X(a) = tZakłada się obecność destruktora
X u(a); SGI: pre: a musi być zainicjalizowane
post: *a = t jest takie samo jak *u = tX u = a;
*a = t nieużywany SGI: pre: a jest dereferencable
po poprzednim przypisaniu było wykonane zwiększenie a
++r X& &r == &++r
r++ konwertowalny do const
X&
{ X tmp = r; const X& ++r; return tmp; }
*r++ = t nieużywany
Output iterator - uwagi
operator * może zostać użyty jedynie po lewej stronie wyrażenia przypisania
przypisanie poprzez wartość iteratora odbywa się tylko raz
nigdy nie należy przechodzić po tych samych wartościach iteratora więcej niż raz
== i != mogą być niezdefiniowane
Forward iterator - wymagania
Operacja Typ Semantyka, założeniaX u; u może być niezainicjowane, zakładane jest istnienie
destruktora
X u(a);X u = a;
X równoważne: X u; u = a;
post: u == a
X(a) X X(a) == a
a == b convertible to bool
== jest relacją równości (w matematycznym sensie) zdefiniowaną na dziedzinie wartości iteratora
a != b convertible to bool
!(a==b)
r = a X& post: r == a
Forward iterator – wymagania c.d.
Operacja Typ Semantyka, założenia*a T& pre: a jest dereferenceable
Jeśli a == b, to *a == *bJeśli X jest typem mutowalnym, to *a = t jest
poprawne
a->m pre: (*a).m jest dobrze zdefiniowaneSemantyka jest taka sama jak (*a).m
++r X& pre: r jest dereferenceablepost: r jest dereferenceable lub r jest wartością
past-the-endJeśli r == s i r jest dereferencable, to ++r ==
++s.&r == &++r
r++ konwertowalny do const X&
{ X tmp = r; ++r; return tmp; }
*r++ T&
Bidirectional iterator – dodatkowe wymagania
Operacja Typ Semantyka, założenia
--r X& pre: istnieje s takie, że r == ++s.post: r jest dereferenceable.
Jeśli –r == --s, to r == s.&r == &--r.--(++r) = r.
r-- konwertowalny do const X&
{ X tmp = r; --r; return tmp; }
*r-- konwertowalny do T
Random access iterator - wymagania
Operacja Typ Semantyka, założeniar += n X& { Distance m = n;
if (m >= 0) while (m--) ++r; else while (m++) --r;
return r; }
a + nn + a
X { X tmp = a;return tmp += n; }
założenie: a + n == n + a
r -= n X& return r += -n;
a – n X { X tmp = a;return tmp -= n; }
b – a Distance pre: Istnieje wartość n typu Distance taka, że
a + n == b.
b == a + (b – a).
(a < b) ? distance(a, b) : -distance(b, a).
Random access iterator – wymagania c.d.
Operacja Typ Semantyka, założeniaa[n] konwertowalny
do T*(a + n)
a < b konwertowalny do bool
true wtw., gdy b – a > 0.> jest relacją porządku liniowego.
a > b konwertowalny do bool
równoważne z b < a.
> jest relacją porządku liniowego
a <= b konwertowalny do bool
takie samo jak: !(a > b)
a >= b konwertowalny do bool
takie samo jak: !(a < b)
Przykłady
int main(){int array [1000], *i; int n = 0; i = array;while (cin >> *i) ++i;++i;sort (array, i); for (j = array; i != j; j++) cout << *j << "\n";
}
Przykład
int main () {
vector<int> v; int input; while (cin >> input) v.push_back (input);sort(v.begin(), v.end()); for (vector<int>::iterator i = v.begin(); i != v.end(); i++)
cout << *i << "\n"; }
Obiekty funkcyjne
Obiekty funkcyjne to obiekty, które mają zdefiniowany operator ()
Są ważną częścią biblioteki STL, zapewniają one efektywność Wszędzie tam, gdzie szablony algorytmów oczekują
wskaźników do funkcji, można stosować obiekty funkcyjne Używanie obiektów funkcyjnych razem z szablonami funkcji
zwiększa siłę wyrazu biblioteki, a także zwiększa efektywność kodu
Obiekty funkcyjne – przykłady
dodanie elementów dwóch wektorów (double) a, b do siebie
transform(a.begin(), a.end(), b.begin(), a.begin(), plus<double>());
zanegowanie wszystkich elementów a:
transform(a.begin(), a.end(), a.begin(), negate<double>());
Obiekty funkcyjne
template <class Arg, class Result> struct unary_function {
typedef Arg argument_type;typedef Result result_type;
};
template <class Arg1, class Arg2, class Result> struct binary_function {
typedef Arg1 first_argument_type;typedef Arg2 second_argument_type;typedef Result result_type;
};
Obiekty funkcyjne – przykłady
template <class T> struct plus : binary_function<T,T,T> { T operator()(const T& x, const T& y) const;
};
Obiekt funkcyjny obliczający x + y.
template <class T> struct negate : unary_function<T,T> { T operator()(const T& x) const;
};
Obiekt funkcyjny obliczający –x.
Obiekty funkcyjne – przykłady
template <class Operation> class binder1st : public unary_function<Operation::second_argument_type, Operation::result_type> { protected:
Operation op; Operation::first_argument_type value;
public: binder1st(const Operation& x, const
Operation::first_argument_type& y); result_type operator()(const argument_type& x) const;
}; Konstruktor inicjalizuje op na x, value na y Operator () zwraca op(value, x) template <class Operation, class T>
binder1st<Operation> bind1st(const Operation& op, const T& x);
EqualityComparable
Typ T jest EqualityComparable jeśli ma zdefiniowany operator ==, którego wynik jest konwertowalny do bool oraz
== jest relacją równości spełniającą założenia:- Dla każdego a: a == a- Jeśli a == b, to b == a- Jeśli a == b i b == c, to a == c
Algorytmy Non-mutating template <class InputIterator, class UnaryFunction>
UnaryFunction for_each(InputIterator first, InputIterator last, UnaryFunction f);
Efekt: Zaaplikowanie f do wyników dereferencii kolejnych wartości iteratora w przedziale [first, last), zaczynając od first i kontynuując aż do last - 1. Wymagania: f nie powinno wywoływać żadnych funkcji, które nie są zadeklarowane jako stałe dla wartości iteratora. Zwraca: f. Złożoność: f jest wywoływana dokładnie last - first razy. Uwaga: Jeśli f zwraca jakąś wartość wynik jest ignorwany.
template <class InputIterator, class EqualityComparable>iterator_traits<InputIterator>::difference_type count(InputIterator first, InputIterator last, const EqualityComparable& value); Wymagania: Typ T jest EqualityComparable.Efekt: Zwraca liczbę iteratorów i z przedziału [first, last), dla których warunek: *i == value.
Algorytmy Non-mutating
template<class InputIterator, class EqualityComparable> InputIterator find(InputIterator first, InputIterator last, const EqualityComparable& value)Wymagania: Typ T is EqualityComparable.Wynik: Pierwszy iterator i z przedziału [first, last), dla którego prawdziwy jest warunek: *i == value. Jeśli żaden iterator z tego przedziału nie spełnia tego warunku zwracany jest last.
template<class InputIterator, class OutputIterator> OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result); Efekt: kopiuje elementy z przedziału [first, last) do [result, result+(last-first)) zaczynając od first i kontynuując aż do last. Dla każdej nieujemnej liczby n < (last-first), wykonuje *(result+n) = *(first+n). Wynik: result + (last - first). Wymagania: result nie powinien być z przedziału [first, last). Złożoność: dokładnie last - first przypisań.
Przykład:
template<class T> struct print : public unary_function<T, void>{ print(ostream& out) : os(out), count(0) {} void operator() (T x) { os << x << ' '; ++count; } ostream& os; int count;};
int main(){ int A[] = {1, 4, 2, 8, 5, 7}; const int N = sizeof(A) / sizeof(int);
print<int> P = for_each(A, A + N, print<int>(cout)); cout << endl << P.count << " objects printed." << endl;}
Gdzie szukać informacji?
Musser Saini, STL Tutorial and Reference Lippman, "Istota jezyka C++„N.M.Josuttis, C++ bibliotek standardowa
podrecznik programistywww-d0.fnal.gov/~dladams/cxx_standard.pdfhttp://anubis.dkuug.dk/jtc1/sc22/open/n2356/
Gdzie szukać informacji?
http://www.sgi.com/tech/stl/ - implementacja STL firmy Silicon Graphics, Inc. (SGI)
http://www.informatik.hs-bremen.de/~brey/stlbe.html - książka "Designing Components with the C++ STL"
http://www.xraylith.wisc.edu/~khan/software/stl/STL.newbie.html - strona o STL z 1995 roku
http://www.cs.brown.edu/people/jak/proglang/cpp/stltut/tut.html - prosty tutorial
http://www.cs.rpi.edu/~wiseb/xrds/ovp2-3b.html - krótki opis STL'a http://pages.cpsc.ucalgary.ca/~kremer/STL/1024x768/index.html -
strona o STL'u
Dziękuję za uwagę!