Both sides previous revisionPrevious revisionNext revision | Previous revisionLast revisionBoth sides next revision |
cpp:stl:containers [2021/06/06 06:49] – gthanos | cpp:stl:containers [2021/06/06 07:55] – gthanos |
---|
| |
====== STL Containers ====== | ===== STL Containers ===== |
| |
Στο παρακάτω διάγραμμα περιέχονται το σύνολο των //containers// που παρέχει η βιβλιοθήκη //STL//. | Στο παρακάτω διάγραμμα περιέχονται το σύνολο των //containers// που παρέχει η βιβλιοθήκη //STL//. |
| |
| |
===== Κοινά χαρακτηριστικά για όλους τους containers ===== | |
| |
==== Αντιγραφή των στοιχείων προς ένθεση μέσα σε ένα Container ==== | |
| |
=== Χρήση Copy-Constructor ή άλλου κατασκευαστή === | |
| |
Κατά την ένθεση ενός στοιχείου σε ένα //container//, δημιουργείται πάντοτε ένα αντίγραφο του στοιχείου σε αυτόν. Για παράδειγμα, για την ένθεση στοιχείων της κλάσης [[https://courses.e-ce.uth.gr/ECE326/doku.php?do=export_code&id=cpp:templates&codeblock=0|Student]] μέσα σε ένα //container list// τα στοιχεία θα αντιγραφούν εντός του //list// στο τέλος της λίστας (οι μέθοδοι //insert_back// και //emplace_back// εισάγουν στο τέλος της λίστας) ως εξής: | |
| |
<code cpp 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].getName(), students[i].getAEM()); | |
//mylist.emplace(mylist.end(), students[i].getName(), students[i].getAEM()); // 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; | |
} | |
</code> | |
| |
<WRAP todo 80% center round> | |
Κατεβάστε, μεταγλωττίστε και εκτελέστε το παραπάνω πρόγραμμα. Ποιος κατασκευαστής καλείται κατά την κατασκευή των αντικείμενων μέσω της συνάρτησης //push_back//. Δοκιμάστε να αντικαταστήσετε τη //push_back// με την //emplace_back// και δοκιμάστε να μεταγλωττίσετε-εκτελέσετε ξανά. Παρατηρήστε τις διαφορές στις εκτυπώσεις στις δύο περιπτώσεις. | |
</WRAP> | |
| |
Κατά την εισαγωγή ενός στοιχείου μέσω των συναρτήσεων //insert//, //insert_back//, //emplace//, //emplace_back// δημιουργείται πάντα ένα νέο αντικείμενο στον //container//. Η δημιουργία του αντικείμένου γίνεται είτε μέσω του copy-constructor (μέθοδοι //insert//, //insert_back//) ή μέσω εκείνου του κατασκευαστή που λαμβάνει ως παραμέτρους τους τύπους των ορισμάτων που περνιούνται στις μεθόδους //emplace// ή //emplace_back//. Στο παράδειγμα μας, τα αντικείμενα κατασκευάζονται με τη βοήθεια του κατασκευαστή ''Student(const char *name, int aem)''. | |
| |
=== Χρήση operator = === | |
| |
Αντιστοίχως, στο παρακάτω πρόγραμμα ανατίθεται σε ένα //container// τύπου //array// περιεχόμενα μέσω του τελεστή %%[]%%. Μεταγλωττίζοντας και εκτελώντας το πρόγραμμα θα παρατηρήσετε ότι καλείται ο τελεστής %%=%% (//operator=//) της κλάσης //Student//. | |
| |
<code cpp student_array.cpp> | |
#include <iostream> // std::cout | |
#include <algorithm> // std::copy | |
#include <array> // std::array | |
#include <array> // std::array | |
#include "Student.hpp" | |
| |
int main () { | |
Student students[] = { Student("Peter_Pan", 1234), Student("Tinker_Bell", 1235) }; | |
| |
std::cerr << "----- Init array -----" << std::endl; | |
std::array<Student,2> myarray; | |
for(int i=0; i<2; i++) { | |
myarray[i] = students[i]; | |
} | |
| |
std::cerr << "-------------------------\n"; | |
std::cerr << "myarray contains:"; | |
for (std::array<Student,2>::iterator it = myarray.begin(); it!=myarray.end(); ++it) | |
std::cerr << ' ' << *it; | |
std::cerr << std::endl; | |
std::cerr << "-------------------------\n"; | |
| |
return 0; | |
} | |
</code> | |
| |
==== Προσδιορισμός εύρους στοιχείων ==== | |
| |
Όταν στην STL προσδιορίζεται ένα εύρος στοιχείων εντός ενός //container// μεταξύ των υποτιθέμενων θέσεων //**start**// και //**stop**// ( οι θέσεις αυτές προσδιορίζονται πάντοτε από //iterators//), το διάστημα το οποιό υπολογίζεται είναι από //**start**// (συμπεριλαμβανομένου) έως και //**stop**// (μη συμπεριλαμβανομένου), ισοδύναμα: **[start, stop)**. Η παρακάτω εικόνα περιγράφει το διάστημα μεταξύ των θέσεων //start=1// και //stop//=6 ενός πίνακα. Το προσδιορισθέν διάστημα είναι από //start// έως και //stop-1//, δηλαδή από 1 έως και 5 (με πράσινο χρώμα). | |
| |
{{ :cpp:stl:stl_range.png?400 |}} | |
| |
Δείτε το παρακάτω παράδειγμα, όπου αντιγράφονται τα περιεχόμενα του πίνακα //array// αρχικά στον πίνακα //myarray// και στη συνέχεια ένα μέρος από αυτά στη λιστα //mylist//. | |
| |
<code cpp int_range.cpp> | |
#include <iostream> // std::cout | |
#include <list> // std::list | |
#include <array> // std::array | |
#define SIZE 10 | |
| |
int main () { | |
int array[] = { 1,2,3,4,5,6,7,8,9,10 }; | |
| |
std::array<int,SIZE> myarray; | |
for(int i=0; i<SIZE; i++) | |
myarray[i] = array[i]; | |
| |
std::cerr << "myarray contains:"; | |
for (std::array<int,SIZE>::iterator it = myarray.begin(); it!=myarray.end(); ++it) | |
std::cerr << ' ' << *it; | |
std::cerr << std::endl; // myarray: 1 2 3 4 5 6 7 8 9 | |
| |
std::list<int> mylist; | |
mylist.assign(myarray.cbegin() + 1, myarray.cbegin() + 4); | |
std::cerr << "mylist contains:"; | |
for (std::list<int>::iterator it = mylist.begin(); it!=mylist.end(); ++it) | |
std::cerr << ' ' << *it; | |
std::cerr << std::endl; // mylist: 2 3 4 | |
| |
return 0; | |
} | |
</code> | |
| |
<WRAP tip 80% center round> | |
Η μέθοδος [[http://www.cplusplus.com/reference/list/list/assign/|assign]] δημιουργεί ένα αντίγραφο των περιεχομένων ξεκινώντας από το πρώτο όρισμα (συμπεριλαμβανομένου) έως και το δεύτερο όρισμα (μη συμπεριλαμβανομένου). Στο παραπάνω παράδειγμα ξεκινά από τη θέση **1** του πίνακα (**myarray.cbegin()+1**) έως και τη θέση **3** (**myarray.cbegin()+3**). Η θέση **myarray.cbegin()+4** που είναι το 2ο όρισμα δεν περιλαμβάνεται στο διάστημα. | |
</WRAP> | |
| |
Σε αναλογία μετα παραπάνω, όπως θα δούμε στη συνέχεια, οι //iterators// της //STL// διατρέχουν οποιαδήποτε δομή από τη θέση //begin()// (δείκτης στην πρώτη θέση περιεχομένων του //container//) έως //end()// (δείκτης αμέσως μετά την τελευταία θέση περιεχομένων του //container//). | |
| |