User Tools

Site Tools


cpp:stl:intro

This is an old revision of the document!


Standard Template Library (STL)

H Standard Template Libray (STL) είναι βιβλιοθήκη της C++ που αποτελεί αναπόσπαστο τμήμα της stardard βιβλιοθήκης της γλώσσας. Αποτελείται από κλάσεις για προσωρινή αποθήκευση πληροφορίας σε ένα πρόγραμμα που ονομάζονται containers, κλάσεις για διάτρεξη των containers (ονομάζονται iterators) και αλγορίθμους. Οι αλγόριθμοι είναι συναρτήσεις που κατά κανόνα λειτουργούν με την βοήθεια των iterators πάνω στους διαθέσιμους containers.

Βασικό χαρακτηριστικό της STL είναι ότι οι κλάσεις (containers και iterators) και οι συναρτήσεις των αλγορίθμων είναι γενικευμένες, ώστε να μπορούν να εφαρμοστούν με ασφάλεια σε οποιονδήποτε τύπο δεδομένων. Για να το επιτύχουν αυτό, χρησιμοποιούν templates.

STL Containers

Στο παρακάτω διάγραμμα περιέχονται το σύνολο των containers που παρέχει η βιβλιοθήκη STL.

Οι containers της STL διακρίνονται στις εξής κατηγορίες:

  • Sequence containers: Αποθηκεύουν τα δεδομένα σειριακά, οδηγώντας σε χρόνους αναζήτησης γραμμικούς στο μέγεθος του πλήθους των στοιχείων που είναι αποθηκευμένα. Παραδείγματα τέτοιων containers είναι
    • array: Πίνακας σταθερού μεγέθους το οποίο προσδιορίζεται κατά τη δήλωση του πίνακα.
    • vector: Πίνακας μεταβλητού μεγέθους. Παρέχει δυνατότητα εισαγωγής στοιχείων σε οποιαδήποτε θέση του πίνακα. Η εισαγωγή/διαγραφή στο/από το τέλος του πίνακα είναι πράξη σταθερού κόστους, ενώ η εισαγωγή σε ή η διαγραφή από ενδιάμεση θέση συνεπάγεται την αντιγραφή των αποθηκευμένων στοιχείων που βρίσκονται μετά από τη συγκεκριμένη εγγραφή κατά μία θέση και είναι ανάλογη του μήκους αυτού.
    • dequeue: Πρόκειται για την γνωστή διπλοουρά που επιτρέπει την γρήγορη ένθεση και διαγραφή από την αρχή και το τέλος της ουράς. Για την εισαγωτή ή διαγραφή από ενδιάμεση θέση απαιτείται η αντιγραφή των στοιχείων που βρίσκονται πριν ή μετά τη συγκεκριμένη θέση κατά μία θέση και όπως και στην κλάση vector είναι ανάλογη του μήκους αυτού.
    • list: Πρόκειται για την διπλά συνδεδεμένη λίστα. Η λίστα δίνει την δυνατότητα διάτρεξης της δομής και προς τις δύο κατευθύνσεις, την εισαγωγή σε συγκεκριμένη θέση ή την διαγραφή στοιχείου από συγκεκριμένη θέση (δες σε αντιδιαστολή τη forward_list). Το κόστος αναζήτησης είναι ανάλογο των στοιχείων που είναι αποθηκευμένα στη λίστα, ενώ το κόστος εισαγωγής στοιχείου και διαγραφής στοιχείου είναι σταθερό. Η επιπλέον ευελιξία που παρέχεται σε σχέση με την forward list, έχει ως κόστος την διαχείριση ενός επιπλέον δείκτη σε κάθε κόμβο της λίστας σε σχέση με την απλά συνδεδεμένη λίστα.
    • forward_list: Πρόκειται για την απλά συνδεδεμένη λίστα. Η λίστα δίνει την δυνατότητα διάτρεξης της δομής προς τη μία κατεύθυνση (από την αρχή προς το τέλος). Για την εισαγωγή και διαγραφή θα πρέπει οπωσδήποτε να γνωρίζουμε τον προηγούμενο κόμβο (θέση). Το κόστος αναζήτησης είναι ανάλογο των στοιχείων που είναι αποθηκευμένα στη λίστα, ενώ το κόστος εισαγωγής στοιχείου και διαγραφής στοιχείου είναι σταθερό.
  • Container Adapters: Χρησιμοποιούν εσωτερικά ένα sequence container για να υλοποιήσουν την λειτουργικότητα τους. Οι βασικές κλάσεις είναι οι εξής:
    • stack: Υλοποιεί μία δομή Last-In-First-Out (LIFO) με την βοήθεια ενός vector ή deque.
    • queue: Υλοποιεί μία δομή First-In-First-Out (FIFO) με την βοήθεια ενός deque.
    • priority_queue: Υλοποιεί μία ουρά προτεραιότητας. Προκειμένου να επιτευχθεί η προτεραιότητα κατά την εισαγωγή και διαγραφή στοιχείου εφαρμόζεται ο αλγόριθμος make_heap για την επίτευξη σωρού με λογαριθμικό κόστος στο μέγεθος των αποθηκευμένων στοιχείων της δομής.
  • Associative Containers: Πρόκειται για δομές που τα στοιχεία εισάγονται ταξινομημένα σε αύξουσα σειρά. Η αποθήκευση γίνεται σε ένα ισοζυγισμένο δέντρο αναζητήσεως (π.χ.Red–black_tree) και ο χρόνος αναζήτησης, εισαγωγής και διαγραφής είναι λογαριθμικός στο μέγεθος των αποθηκευμένων στοιχείων. Διακρίνονται σε sets που είναι σύνολα από μοναδικά στοιχεία-κλειδιά και maps που είναι συνολά από απεικονίσεις μοναδικών στοιχείων-κλειδιών σε τιμές. Παραλλαγές των παραπάνω κλάσεων είναι τα multiset και multimap όπου δίνεται η επιπλέον δυνατότητα αποθήκευσης περισσότερων του ενός ίδιων κλειδιών στην υφιστάμενη δομή.
  • Unordered Associative Containers: Δομές ανάλογες με τους Associative Containers με την διαφορά ότι η αποθήκευση δεν γίνεται σε ισοζυγισμένο δέντρο αναζητήσεως, αλλά σε πίνακα κατακερματισμού (Hash_table). Για τον λόγο αυτό, τα στοιχεία δεν αποθηκεύονται ταξινομημένα, αλλά με “τυχαία” σειρά. Η σειρά διάτρεξης τους αντιστοιχεί στη σειρά που τα κλειδιά είναι αποθηκευμένα στον πίνακα κατακερματισμού. Ο μέσος χρόνος αναζήτησης, εισαγωγής και διαγραφής είναι σταθερός στο μέγεθος των αποθηκευμένων στοιχείων, ενώ ο απαιτούμενος χώρος είναι περισσότερος (κατ' ελάχιστο διπλάσιος από τον αριθμό των αποθηκευμένων στοιχείων στην δομή). Οι κλάσεις unordered_set και unordered_map επιτρέπουν την αποθήκευση μοναδικών κλειδιών, ενώ οι δομές unordered_multiset και unordered_multimap επιτρέπουν την αποθήκευση περισσότερων του ενός ιδίων στοιχείων-κλειδιών στη δομή.

Κοινά χαρακτηριστικά για όλους τους containers

Αντιγραφή των στοιχείων προς ένθεση μέσα στον Container

Κατά την ένθεση ενός στοιχείου σε ένα container, δημιουργείται πάντοτε ένα αντίγραφο του στοιχείου σε αυτόν. Για παράδειγμα, για την ένθεση στοιχείων της κλάσης Student μέσα σε ένα container list τα στοιχεία θα αντιγραφούν εντός του list ως εξής:

student_list.cpp
#include <iostream>     // std::cout
#include <algorithm>    // std::copy
#include <list>       // std::list
#include <array>        // std::array
#include "Student.hpp"
 
int main () {
  Student students[] = { Student("Peter_Pan", 1234), Student("Tinker_Bell", 1235) };
 
  std::cerr << "----- Init list -----" << std::endl;
  std::list<Student> mylist;
  for(int i=0; i<2; i++) {
    mylist.push_back(students[i]);
    //mylist.insert(mylist.end(),students[i]);                         // equivalent with push_back
    //mylist.emplace_back(students[i].name, students[i].aem);
    //mylist.emplace(mylist.end(), students[i].name, students[i].aem); // equivalent with emplace_back
  }
 
  std::cerr << "-------------------------\n";
  std::cerr << "mylist contains:";
  for (std::list<Student>::iterator it = mylist.begin(); it!=mylist.end(); ++it)
    std::cerr << ' ' << *it;
  std::cerr << std::endl;
  std::cerr << "-------------------------\n";
 
  return 0;
} 

Κατεβάστε, μεταγλωττίστε και εκτελέστε το παραπάνω πρόγραμμα. Ποιος κατασκευαστής καλείται κατά την κατασκευή των αντικείμενων μέσω της συνάρτησης push_back. Δοκιμάστε να αντικαταστήσετε τη push_back με την emplace_back και δοκιμάστε να μεταγλωττίσετε-εκτελέσετε ξανά. Παρατηρήστε τις αλλαγές στις εκτυπώσεις.

Κατά την εισαγωγή ενός στοιχείου μέσω των συναρτήσεων insert, insert_back, emplace, emplace_back δημιουργείται ένα νέο αντικείμενο μέσω στον container. Η δημιουργία του αντικείμένου γίνεται είτε μέσω του copy-constructor (μέθοδοι insert, insert_back) ή μέσω του κατασκευαστή που λαμβάνει τα ορίσματα που περνιούνται στις μεθόδους emplace και emplace_back.

Όταν στην STL προσδιορίζεται ένα εύρος στοιχείων εντός ενός container μεταξύ των υποτιθέμενων θέσεων start και stop (προσδιορίζονται πάντοτε από iterators) το διάστημα το οποιό υπολογίζεται είναι από start (συμπεριλαμβανομένου) έως και stop (μη συμπεριλαμβανομένου)

Κοινές συναρτήσεις για όλους τους containers

Εισαγωγή στοιχείου σε container

Με εξαίρεση την κλάση std::array που το μέγεθος των πινάκων που δημιουργεί είναι σταθερό οι υπόλοιποι containers μπορούν να μεταβάλλουν το αριθμό των στοιχείων που αποθηκεύουν. Για την εισαγωγή ενός στοιχείου σε έναν container υπάρχει η συνάρτηση μέλους insert. Για sequence containers η insert λαμβάνει ως πρώτο όρισμα έναν iterator που δηλώνει τη θέση εισαγωγής

cpp/stl/intro.1590675506.txt.gz · Last modified: 2020/05/28 13:18 (external edit)