STL (STANDART TEMPLATE LIBRARY)
STL (STANDART TEMPLATE LIBRARY)
The Standard Template Library (STL) is a set of C++ template classes to provide common
programming data structures and functions such as lists, stacks, arrays, etc. It is a library of container
classes, algorithms, and iterators.
STL has 3 compunents:
CONTAINERS
ITERATORS
ALGORITHMS
Containers
Containers or container classes store objects and data. There are in total seven standards “first-class”
container classes and three container adaptor classes and only seven header files that provide access
to these containers or container adaptors.
Sequence Containers: implement data structures that can be accessed in a sequential manner.
vector
list
deque
arrays
forward_list( Introduced in C++11)
Container Adaptors: provide a different interface for sequential containers.
queue
priority_queue
stack
Associative Containers: implement sorted data structures that can be quickly searched (O(log n)
complexity).
set
multiset
map
multimap
Unordered Associative Containers: implement unordered data structures that can be quickly
searched
unordered_set (Introduced in C++11)
unordered_multiset (Introduced in C++11)
unordered_map (Introduced in C++11)
unordered_multimap (Introduced in C++11)
Iterator:
Iterators are used to point at the memory addresses of STL containers. They are primarily used in
sequences of numbers, characters etc. They reduce the complexity and execution time of the program.
***STL nesne yonelimli programlama degildir. OOP yok. Runtime polymorphism yok.
**range--->**aralik
[konum1 konum2)
range konum1 arttirildiginda konum2 ye ulasmadir.
Derleyicinin yazdigi kod:
utility dosyasi kullanilarak fonk kullanma:
stl siralama fonk kullanilarak:
Bir oyun programinda fighter isimli bir vector de en güclu savascilari en basta tutmak istediniz. Bunu
yine STL in sort isimli siralama fonk ile yapabilir miydiniz? evet yapabilirdiniz. Iste Generic programlama
budur. Fighter oyun ögeleri nerede, string ögeleri nerede ne alaka.. Ama tek fonk(ayni generic kodla) ile
ikisinide siralayabiliyoruz.
SORU: Neden STL'i böyle tasarlamislar?
Yani bu fonksiyon sablonlari parametreleri dogrudan container olsun. Bir container'in uzerinde islem
yapabilmek icin fonk sablonlari iteratorleri kullaniyor. Onun yerine ben direk container nesnesinin
kendisini gonderseydim daha dogru olmaz miydi?
Container da tutulan ogelerin tamaminda islem yapmak zorunda degiliz ki. Burada range kavrami cok
onemli oldugu ortaya cikiyor. Bu sayede belli bir range uzerinde islem yapabilmis oluyoruz.
Peki bunu Cpp kendi argumanlari ile saglayamaz miydik? Evet 2020 ile bu özellik geldi.
STL de en cok kullanilan algoritmalardan biri copy...
copy: Bir range deki ogeleri bir range'e kopyaliyor. STL'in en onemli avantajlarindan bir farkli veri
yapilari ögeleri üzerinde islemleri yapabilmesi.
OutIter Copy(InIter beg, InIter end, OutIter destbeg);
****STL'in en onemli convensiyonlarindan biri: Kaynak range her zaman basta yazilir. Yani Copy fonk
kaynak range: InIter beg, InIter end,
Copy fonk hedef: OutIter destbeg
****STL'in en onemli convensiyonlarindan biri: Eger bir algoritma bir range'i yazma yapiyorsa yani bir
range'deki ögelerin degerini degistirmeye yonelikse, fonksiyonun geri dönüs degeri herzaman en son
yazdigi ögenin konumundaki sonraki konum olur. Yani yazma yaptigi konumun end konumunu dönecek.
end() konumu neresi? Burayi cok iyi anlamamiz gerekir.
Cantainer begin fonk, container'in ilk elemanininin konumunu döndürüyor. Ama end fonsiyonu
container'in son ögenin konumu degil. Son ögeden sonraki konumu döndürüyor!!
Bu durumda end() fonksiyonunun geri döndürdügü konumu dereferans etmemelisiniz. Tanimsiz
davranis olur.
auto iter_end=ivec.end();
*iter_end--->UB
STL copy fonksiyonunu kendimiz yazalim:
STL'in yazdigi kod:
****Burada STL'in farkli containr'ler arasinda atama yapabildigini görüyoruz.
****Burada STL'in farkli türler arasinda atama yapabildigini görüyoruz.
GLOBAL begin(), end() fonksiyonlari
int main()
{
std::vector<int> ivec;
ivec.begin(); // Sinifin üye fonsksiyonuna yapilan cagri
begin(ivec); //global fonksiyona yapilan cagri
}
*****Sinifin üye fonksiyonuna yapilan cagri ile global fonksiyona yapilan cagri arasinda bir fark yoktur.
Bu ornekte a.begin() yazabilir miydim?
Hayir! a bir sinif nesnesi degil ki!
Fakat a dizisi icin global begin() ve end() fonksiyonlarini kullanabilirim.
**Iste burada cikarilan sonuc: Container'lar icin Sinifin üye fonksiyonuna yapilan cagri ile global
fonksiyona yapilan cagri arasinda bir fark yoktur. Fakat diziler icin mecburi global fonksiyona yapilan
cagri ile end() ve begin() foknsiyonlari cagrilabilir.
ITERATOR CATEGORY
Bir iteratorun en onemli ozelligi o Iteratorun kategorisidir. Iterator kategorisi bize o Iterator ile hangi
islemleri yapabilecegimizi gosterir.
Toplam 5 adet kategory var:
Iterator Kategorilerinin Özellikleri:
Random-Access kategorisi raw-pointer'larinin yaptigi herseyi yapabiliyor.
Container'larin sahip olduklari kategoriler:
using Con= std::vector<int>;
int main()
{
using namespace std;
Con c(5);
iter++; //gecerli
iter--; //gecerli
iter-iter; //gecerli
iter>iter; //gecerli
vector<int> ivec{1,2,3,4,5};
ivec.end()-1; //gecerli
list<int> ilist{1,2,3,4,5};
ilist.end()-1; //gecersiz
auto iter=ilist.end();
--iter; //gecerli
forward_list<int> flist{1,2,3,4,5};
flist.end()-1; //gecersiz
auto fter=flist.end();
--fter; //gecersiz
}
Iteratorlerin kategorisini bulma:
Sort algoritmasi minimal olarak random-access iterator kategorisinde iterator istiyor benden, bu
durumda sort algoritmasi vector icin gecerli iken list container icin syntak hatasi verecektir.
Dolayisiyla bir algoritmaya cagri yaptigimizda algoritma bizden belli bir düzeydeki iterator kategorisi
beklentisi olacak.
Ornek: UB
bu ornegin UB olmasinin sebebi copy algoritmasi beg iteratorunu dereferans ediyor. Bos durumdaki list
iteratorunu dereferans ettigimizde yada ++ ettigimizde bu durumda UB olur.
copy_if