Sunteți pe pagina 1din 10

Ce este STL (Standard Template Library) ?

Autor: Prof. Tudor Sorin


Creatorul limbajului C++, Bjarne Stroustrup, i-a pus problema s adauge 1 limbajului anumite elemente astfel nct scrierea programelor s se fac rapid , 2 3 strandardizat i programele obinute s fie performante . Atunci cnd scriem programe, utilizm dou noiuni fundamentale: algoritmi i structuri de date. De aici, rezult c: 1. Limbajul trebuie s conin anumite clase care s gestioneze structurile de date frecvent utilizate. Astfel, vom avea clase specializate n gestionarea vectorilor, listelor liniare, stivelor, cozilor, heap-urilor, etc. Astfel de clase se numesc clase de tip container, iar obiectele generate prin instanierea lor se numesc containere. Prin urmare, o structur de tip list liniar este un container, o structur de tip stiv este un container, .a.m.d. 2. ntruct o structur de date trebuie s opereze cu date de orice tip, clasele de tip container utilizeaz din plin mecanismul template. Astfel, la modul general, un container se definete ca un obiect care poate reine alte obiecte. 3. Aa cum am vzut, structurile de date nu sunt suficiente pentru realizarea programelor. Din acest motiv, este necesar s avem anumite funcii care incorporeaz algoritmii cei mai des folosii. Funciile care incorporeaz algoritmii, trebuie s poat lucra cu orice tip de dat (la modul general cu orice obiect). Cerina este satisfcut dac aceste funcii utilizeaz i ele mecanismul template. De asemenea, este foarte important ca aceste funcii s poat lucra cu datele stocate n containere.
1

Un program se realizeaz cu mult mai repede dac limbajul dispune de funcii i clase, care pot fi adaptate uor pentru rezolvarea unor probleme concrete, cerute de practic.
2

Scrierea programelor nu mai este de mult o activitate artizanal. Este esenial ca un program s poat fi neles i de ali programatori, nu numai de cei care l-au scris. De exemplu, o firm cu acest profil, trebuie s-i poat uor modifica programele, chiar dac unii dintre cei care le-au realizat nu mai lucreaz acolo.
3

Pentru a obine programe performante prin utilizarea funciilor i claselor puse la dispoziie de limbaj, este esenial ca acestea din urm s aib, la rndul lor, la baz algoritmi performani. 1 www.infobits.ro | www.lswww.ls-infomat.ro

CE ESTE STL (STANDARD TEMPLATE LIBRARY) ?

Ca terminologie, vom utiliza termenul algoritm i cu semnificaia de funcie template care rezolv o anumit problem des ntlnit n activitatea curent i care, de regul, prelucreaz date (obiecte) stocate n containere. 4. O problem foarte important este dat de accesul la datele (obiectele) aflate n container. Dac la un container de tip vector, accesul se poate realiza uor, el este mai dificil la un container de tip list liniar sau la unul de tip de arbore de cutare. Din acest motiv, s-au generalizat pointerii i s-a ajuns la iteratori. Un iterator indic un anumit obiect din container. Pornind de la el se pot accesa datele i, dac este cazul, metodele obiectului memorat. De asemenea, se poate obine imediat, printr-o simpl incrementare, un iterator care indic obiectul urmtor din container. IMPORTANT. IMPORTANT. Pentru a accesa datele stocate n containere, algoritmii utilizeaz iteratorii. Acesta este motivul pentru care se spune c iteratorii reprezint un liant ntre containere i algoritmi. Prin STL (Standard Template Library) nelegem o colecie de clase de tip container, algoritmi i iteratori care poate fi folosit pentru a realiza rapid programe performante i standardizate. Orice compilator actual de 4 C++ trebuie s permit utilizarea STL-ului . Prin folosirea STL-ului, obinem programe portabile (pot fi compilate, teoretic, cu orice compilator de C++) i, mai ales, uor de descifrat pentru oricine este familiarizat cu acest mod 5 de lucru .

FOARTE

nvai s v autodocumentai! Prezentm o adres la care putei gsi o documentaie pentru STL: http://www.sgi.com/tech/stl/table_of_contents.html. Dup cum ai vzut, containerele conin obiecte. De cele mai multe ori, acestea sunt de tipuri simple, predefinite, cum ar fi: int, float, char... Mai mult, aceste obiecte sunt supuse unor operaii de comparare. De asemenea, anumite containere sunt de tip vector, list liniar, .a.m.d. Din acest motiv, vom folosi uneori termenii de dat, valoare pentru obiecte sau de component n cazul vectorului, element n cazul listelor (nelegnd prin aceasta, att obiectul memorat, ct i informaia de adres). Sperm ca astfel de exprimri s nu fie considerate o "crim"...

n varianta Borland C++, STL-ul nu poate fi folosit dect parial. Atunci cnd a fost realizat compilatorul (la modul general, mediul de programare), STL-ul era nc n faza de proiectare. Acesta este unul dintre motivele pentru care recomandm utilizarea compilatoarelor prezentate n prima parte a crii. Elevii sunt avantajai dac utilizeaz STL-ul n concursurile colare. Teoretic, nimeni nu-i poate opri s-l utilizeze, este un standard. Totui, utilizarea STL-ului nu-i scutete de pregtirea teoretic. Se poate spune c, ntre doi olimpici cu aceleai cunotine, cel care cunoate STL-ul are un anumit avantaj. 2 www.infobits.ro | www.lswww.ls-infomat.ro
5

CE ESTE STL (STANDARD TEMPLATE LIBRARY) ?

Mai mult despre containere


Containere. Un container este un obiect care reine alte obiecte. El rezult prin instanierea unei clase de tip container. Containerele sunt de dou mari categorii: containere secven i containere asociative. De asemenea, exist o categorie aparte de containere, numite adaptori.

A) Containere secven - rein obiectele ntr-o ordine oarecare. Ordinea obiectelor este stabilit de cel care folosete containerul respectiv. Containerele de tip secven permit inserarea i tergerea obiectelor. Exemple de clase ale cror obiecte sunt containere de tip secven: vector (gestioneaz un vector unde fiecare component reine un obiect) i list (gestioneaz o list liniar dublu nlnuit, unde fiecare element al listei reine un obiect). B) Containere asociative - fiecare obiect are o cheie i poate fi regsit rapid dup aceasta. Regsirea, tergerea i inserarea unui obiect se fac rapid, n O(log n), unde n este numrul obiectelor care se gsesc n container. Pentru astfel de containere se prefer memorarea obiectelor sub forma unor arbori de cutare echilibrai, motiv pentru care operaiile amintite se efectueaz att de eficient. n mod evident, inserarea unui obiect se face automat, acolo unde i este locul, conform cheii pe care o are, nu acolo unde dorete programatorul, ca n cazul containerelor secven. Exemple de clase ale cror obiecte utilizeaz containere asociative: set gestioneaz o mulime de obiecte, unde fiecare obiect coincide cu cheia sa, unic; map gestioneaz mai multe perechi de forma (cheie, valoare), unde cheia este unic; multiset, la fel ca set, dar pot exista mai multe obiecte cu aceeai cheie; multimap, la fel ca map, dar pot exista mai multe perechi cu aceeai cheie. C) Adaptori - sunt tot containere, dar nu sunt definii separat, ci pornind de la alte containere se restricioneaz accesul numai la anumite metode. De exemplu, dac dorim s lucrm cu o stiv, se poate folosi un vector cu acces numai la unul dintre capete. Exemple de adaptori: stack (stiv), queue (coad), priority_queue (coad cu prioritate sau, aa cum este cunoscut din cursul de algoritmi, structura heap).

NOTAII STANDARD. Atunci cnd prezentm


size_type key_type value_type un tip ntreg fr semn

containerele, metodele de acces la obiectele memorate, utilizm urmtoarele notaii:

tipul obiectului care constituie cheia tipul obiectului memorat - n cazul obiectelor de tip map i multimap, este alctuit din cheie i valoare
3 www.infobits.ro | www.lswww.ls-infomat.ro

CE ESTE STL (STANDARD TEMPLATE LIBRARY) ?

Mai mult despre iteratori


Iteratori. Pentru a se accesa cu uurin obiectele unui container (a naviga printre ele) se utilizeaz iteratorii. Iteratorii sunt asemntori pointer-ilor, dar cu ei se pot face mult mai multe lucruri. Dac n cazul containerelor de tip secven, iteratorii sunt aproape la fel ca pointerii, n cazul containerelor asociative, acetia permit navigarea uoar, printr-o simpl incrementare, printre nodurile unui arbore de cutare.

DE REINUT:
1) Iteratorii sunt obiecte ale unor clase. 2) Dac it este o variabil care reine un iterator care indic un anumit obiect al containerului, atunci: prin *it se adreseaz obiectul; prin it->metoda / it->data_membru se adreseaz o metod / dat membru a obiectului memorat; prin ++it se obine adresa obiectului urmtor. Dac semnificaia incrementrii este uor de explicat n cazul containerelor secveniale (++it va indica obiectul urmtor n secven), n cazul containerelor asociative semnificaia poate fi de a indica urmtorul obiect cu cheia mai 6 mare sau mai mic . 3) Prin convenie, s-a stabilit c toate containerele secveniale i asociative s aib un prim element i un ultim element. Acesta din urm nu conine niciun obiect, el este folosit pentru a marca sfritul elementelor din container. Nu exist ca n cazul pointer-ilor un iterator nul, exist numai un iterator care indic ultimul element din structur. 4) Din punct de vedere al sensului de parcurgere a obiectelor din container, iteratorii sunt de dou feluri: a) iterator - prin aplicarea repetat a operatorului ++ se parcurg obiectele n ordinea stabilit, cea secvenial, n cazul containerelor secveniale i cea dat de relaia de ordine pe mulimea cheilor, n cazul containerelor asociative; reverse_iterator - prin aplicarea repetat a operatorului ++ se parcurg obiectele n ordinea invers impus de secven, n cazul containerelor secveniale i ordinea invers relaiei de ordine pe mulimea cheilor, n cazul containerelor asociative.

b)

n cazul tipurilor numerice, semnificaia lui mai mare sau mai mic este evident. n cazurile altor tipuri, semnificaia lui mai mare sau mai mic trebuie precizat (programat). Pe parcursul leciilor urmtoare, vei nelege i cum se realizeaz aceasta. 4 www.infobits.ro | www.lswww.ls-infomat.ro

CE ESTE STL (STANDARD TEMPLATE LIBRARY) ?

5) Clasele care utilizeaz containeri conin unele sau toate metodele de mai jos:
iterator begin() iterator end() reverse_iterator rbegin() returneaz un iterator care indic primul obiect al containerului returneaz un iterator care indic ultimul element al containerului returneaz un reverse_iterator care indic primul obiect al containerului, dac le considerm pe acestea n ordine invers returneaz un reverse_iterator care indic ultimul element al containerului dac le considerm pe acestea n ordine invers

reverse_iterator rend()

6) Declararea unei variabile care reine un iterator se face prin utilizarea operatorului de rezoluie, ca mai jos: a) nume_clasa_container::iterator nume_iterator; b) nume_clasa_container::reverse_iterator nume_iterator; 7) Parcurgerea cu ajutorul iteratorilor a obiectelor dintr-un container, se poate face ca mai jos:
for(it=ob_container.begin();it!=ob_container.end();it++) ... // unde it este iterator for(it=ob_container.rbegin();it!=ob_container.rend();it++) ... // unde it este reverse_iterator

8) n funcie de operaiile care se pot efectua cu ei, principial, iteratorii se pot mpri n urmtoarele categorii: a) Iteratori de tip Input - permit accesul la obiectele din container. Operaiile permise cu acetia sunt: ++ (incrementare, pentru a indica urmtorul obiect), =*p (citiri de obiecte din container), -> (accesul la datele sau metodele obiectului indicat de iterator), == i != (testarea egalitii sau a inegalitii a doi iteratori). b) Iteratori de tip Output - permit memorarea obiectelor n container. Operaiile permise cu acetia sunt: ++, *p= (atribuiri de obiecte n container). c) Iteratori de tip Forward - permit operaiile care se pot efectua cu iteratorii de tip Input i Output. d) Iteratori de tip Bidirectional - permit operaiile care se pot efectua cu iteratorii de tip Forward i, n plus, este permis i operaia -- (se obine un iterator care indic obiectul care precede n secven obiectul indicat de iteratorul memorat). e) Iteratori de tip Random - permit operaiile care se pot efectua cu iteratorii de tip Bidirectional, dar, n plus, se permit operaii genul iterator+k, unde k este un ntreg, adic se poate accesa direct un obiect al containerului, fr a fi necesar s parcurgem toate elementele care l preced. De asemenea, accesul direct la obiecte se poate obine prin suprancrcarea operatorului []. n final, menionm c diversele containere permit lucrul cu o anumit categorie de iteratori. De asemenea i algoritmii lucreaz cu anumii iteratori.
5 www.infobits.ro | www.lswww.ls-infomat.ro

CE ESTE STL (STANDARD TEMPLATE LIBRARY) ?

Un exemplu mult simplificat pentru nelegerea noiunilor de container, iterator i algoritm


Aceast lecie este facultativ i se adreseaz doar acelor elevi care vor s neleag principiile care stau la baza programrii prin utilizarea STL-ului. n ea, vom prezenta o clas, de tip container, care permite lucrul cu vectori. Clasa o vom numi vectoras<T>. Pentru a putea lucra cu vectori, vom utiliza iteratori obinui prin instanierea clasei iterator. De asemenea, se va da un exemplu de algoritm pentru a vedea, n linii mari, cum au fost acetia obinui. Menionm c, n vederea atingerii scopului propus, vom utiliza procedee cu mult simplificate fa de cele care au stat la baza obinerii STL-ui. Totui, parcurgerea acestei lecii constituie i o recapitulare a cunotinelor nsuite n leciile precedente. ncepem prin a prezenta sursa clasei vectoras<T>:
template <class T> class vectoras { // numarul de componente int n; // pointer catre vectorul alocat dinamic T* h; public: // clasa interioara ce are rolul de a genera obiectele iterator class iterator { T* p; public: iterator() {p=0;} iterator(T* adr) {p=adr;}; T& operator*() {return *p;} void operator++() { p++; } void operator=(iterator it1) {p=it1.p;} int operator !=(iterator it1) {return p!=it1.p;} }; // metoda care returneaza un iterator catre prima componenta a // vectorului iterator begin(); // metoda care returneaza un iterator catre ultima componenta a // vectorului iterator end(); // constructorul clasei vectoras(int n); // metoda de acces la componentele vectorului T& operator[](int k); // metoda de adaugare a unei componente la sfarsitul unui vector void push_back (T x); }; 6 www.infobits.ro | www.lswww.ls-infomat.ro

CE ESTE STL (STANDARD TEMPLATE LIBRARY) ? template <class T> vectoras<T>::vectoras(int n) { this->n=n; h=new T[n+1]; } template <class T> T& vectoras<T>::operator[](int k) { return h[k]; } template <class T> typename vectoras<T>::iterator vectoras<T>::begin() { return h; } template <class T> typename vectoras<T>::iterator vectoras<T>::end() { return h+n; } template <class T> void vectoras<T>::push_back(T x) { T* adr=new T[n+1]; int i; for (i=0;i<n;i++) adr[i]=h[i]; adr[n]=x; delete[] h; n++; h=adr; }

S analizm clasa prezentat! 1. Cerina este ca vectorul s poat conine componente de orice tip. Din acest motiv, clasa este una de tip template, iar componentele vectorului au tipul formal T. 2. O alt cerin este ca numrul de componente s fie cunoscut n timpul executrii programului. De aici, rezult c este necesar ca vectorul s fie alocat dinamic. Prin urmare, clasa va conine data membru h, care reine un pointer ctre prima component a vectorului. De asemenea, data membru n va reine numrul de componente ale vectorului. Alocarea vectorului n memorie i iniializarea datelor membru este fcut de ctre constructorul clasei:
template <class T> vectoras<T>::vectoras(int n) { this->n=n; h=new T[n+1]; }

3. Pentru a accesa componentele vectorului n mod clasic, aa cum suntem obinuii, vom suprancrca operatorul [] astfel nct metoda rezultat s ntoarc o referin ctre componenta de indice k.
template <class T> T& vectoras<T>::operator[](int k) { return h[k]; }

Din acest moment, se pot scrie deja primele programe care permit lucrul cu vectori.
7 www.infobits.ro | www.lswww.ls-infomat.ro

CE ESTE STL (STANDARD TEMPLATE LIBRARY) ?

Exemplu. Iat secvenele prin care se citesc i se afieaz doi vectori. Unul cu componente de tip float (stnga), altul cu componente de tip char (dreapta):
vectoras<float> v(5); int i; for (i=0;i<5;i++) cin>>v[i]; for (i=0;i<5;i++) cout<<v[i]; vectoras<char> v(5); int i; for (i=0;i<5;i++) cin>>v[i]; for (i=0;i<5;i++) cout<<v[i];

4. Clasa trebuie nzestrat cu iteratori. Ce sunt ei? Nite pointeri, dar mai evoluai. E drept, efectul utilizrii iteratorilor este evident n cazul altor structuri, mai puin cea de vector. Oricum, pentru simplitate, am preferat s exemplificm crearea acestora pentru vectori.

Ce tim despre iteratori? - Ei sunt obiecte - prin urmare, vom considera clasa iterator, care este nzestrat cu un constructor fr parametri. Clasa iterator este inclus n clasa vectoras<T>. Iat-o:
class iterator { T* p; public: iterator() { p=0; } iterator(T* adr) { p=adr ;}; T& operator*() { return *p; } void operator++() { p++; } void operator=(iterator it1) { p=it1.p; } int operator !=(iterator it1) { return p!=it1.p; } };

- Un iterator indic un anumit obiect al containerului. n cazul de fa, iteratorul va indica o anumit component a vectorului. Prin urmare, clasa va avea ca dat membru un pointer ctre tipul formal T, adic tipul elementelor vectorului, numit p. Constructorul iniializeaz cu 0 data membru. - n vederea parcurgerii elementelor structurii, variabilele de tip iterator se pot incrementa. Semnificaia incrementrii este de a indica adresa urmtorului obiect al containerului. n cazul de fa, semnificaia este de a indica urmtoarea component a vectorului. Pentru a fi permis incrementarea, clasa conine o metod care suprancarc operatorul ++. n fapt, ea va incrementa pointer-ul din data membru p, pointer ce reine adresa unei componente. - Iteratorii suport comparri de genul != (inegal). Din acest motiv, clasa conine o metod care suprancarc operatorul != i returneaz o valoare diferit de 0 n cazul n care iteratorul obiectului curent nu este egal cu iteratorul transmis ca parametru. n fapt, se compar coninuturile datelor membru, p. - ntre variabilele care conin iteratori sunt permise atribuiri. Prin urmare, clasa va conine o metod care suprancarc operatorul = i care permite copierea n obiectul curent a coninutului altui iterator. - Pornind de la un iterator, se poate adresa coninutul obiectului, la fel cum pornind de la un pointer, se poate adresa coninutul unei variabile indicat de el.

8 www.infobits.ro | www.lswww.ls-infomat.ro

CE ESTE STL (STANDARD TEMPLATE LIBRARY) ?

Pentru a realiza aceasta, vectoras<T> conine o clas care suprancarc operatorul * i care ntoarce o referin la obiectul (componenta) indicat de iterator. - n plus, clasa iterator este nzestrat cu un constructor de copiere. Acesta va fi folosit, aa cum vei vedea, de alte metode ale clasei vectoras<T>. Practic, constructorul de copiere obine un obiect iterator pornind de la un pointer ctre un obiect al containerului. 5. Aa cum am nvat n lecia precedent, clasa container conine, de regul, dou metode care returneaz adresa primului obiect din container i adresa ultimului element (cel care nu reine nicio valoare). Pentru aceasta, containerul va avea dou metode: iterator begin() i iterator end(). Prima returneaz un iterator ce conine adresa primei componente a vectorului, coninutul datei membru h. A doua returneaz adresa componentei n+1 care, n mod convenional, nu conine nici un obiect. S observm faptul c cele dou metode returneaz un obiect de tip iterator, dar valoarea returnat este de fapt de tipul T*. Este posibil, deoarece am nzestrat clasa iterator cu un constructor de copiere.
template <class T> typename vectoras<T>::iterator vectoras<T>::begin() { return h; } template <class T> typename vectoras<T>::iterator vectoras<T>::end() { return h+n; }

De acum, putem accesa obiectele prin intermediul iteratorilor pe care i-am construit. Exemplu Iat secvenele prin care, cu ajutorul iteratorilor, se citesc i se afieaz doi vectori: unul, cu componente de tip float (stnga) i altul, cu componente de tip char (dreapta):
vectoras<float> v(5); vectoras<float>::iterator it; for (it=v.begin();it!=v.end(); ++it) cin>>*it; for (it=v.begin();it!=v.end(); ++it) cout<<*it<<" "; vectoras<char> v(5); vectoras<char>::iterator it; for (it=v.begin();it!=v.end(); ++it) cin>>*it; for (it=v.begin();it!=v.end(); ++it) cout<<*it<<" ";

6. De regul, clasele care genereaz containere secveniale conin o metod prin care se poate aduga la sfritul unui container un obiect. n cazul nostru, se poate aduga la sfritul unui vector o component cu o anumit valoare. Metoda se numete push_back(). De fapt, v dai seama, algoritmul const n alocarea dinamic a unui vector cu n+1 componente de tipul T, copierea valorilor primelor n componente n vectorul nou alocat, adugarea noii valori, transmis ca parametru, pe poziia n+1, eliberarea memoriei ocupate de vechiul vector, memorarea n n a noului numr al componentelor i n h, un pointer ctre noul vector.
9 www.infobits.ro | www.lswww.ls-infomat.ro

CE ESTE STL (STANDARD TEMPLATE LIBRARY) ? template <class T> void vectoras<T>::push_back(T x) { T* adr=new T[n+1]; int i; for (i=0;i<n;i++) adr[i]=h[i]; adr[n]=x; delete[] h; n++; h=adr; }

Iat i un exemplu de utilizare a acestei metode:


vectoras<int> v(5); int i; for (i=0;i<5;i++) v[i]=i+1; v.push_back(6); for (i=0;i<6;i++) cout<<v[i];

OBSERVAIE.

Pentru vectori, dei prezent, metoda este un exemplu de ineficien. Desigur, nu se poate spune acelai lucru dac am avea o aceeai metod pentru o list liniar dublu nlnuit. Rmne s exemplificm modul n care se realizeaz un algoritm. Algoritmul acceseaz elementele containerului (n exemplu, vectorul) prin intermediul iteratorilor. El este sub forma unei funcii template i calculeaz suma elementelor din container:
long suma(vectoras<int>::iterator st, vectoras<int>::iterator fin) { long s=0; vectoras<int>::iterator it; for(it=st;it!=fin;++it) s+=*it; return s; }

Iat i o secven care utilizeaz algoritmul: se citete vectorul i se afieaz suma elementelor:
vectoras<int> v(5); vectoras<int>::iterator it; for (it=v.begin();it!=v.end(); ++it) cin>>*it; cout<<"Suma este "<<suma(v.begin(),v.end());

infobits.ro | Editura L&S INFO-MAT v recomand Complemente de C++, autori: Tudor Sorin, Vlad Tudor (Huanu)

10 www.infobits.ro | www.lswww.ls-infomat.ro