- •8.2.1. Реалізація класів
- •8.2.2. Породження об’єктів
- •8.2.3. Виклик операцій
- •8.2.4. Використання успадкування
- •8.2.5. Реалізація залежностей
- •8.2.6. Шаблони, шаблони-класи
- •Параметри шаблонів, що опускаються
- •Приклади, які використовують вектори символів
- •8.2.8. Основні компоненти stl
- •8.2.8.1. Контейнери
- •Контейнери послідовностей
- •Впорядковані асоціативні контейнери
- •8.2.8.2. Параметричні (родові) алгоритми
- •8.2.8.3. Ітератори
- •8.2.8.4. Об’єкти-функції
- •8.2.8.5. Адаптери
- •8.2.8.6. Алокатори
- •8.2.9. Stl та об’єктно-орієнтоване програмування
8.2.8. Основні компоненти stl
STL містить шість основних видів компонентів: контейнери, параметричні (родові) алгоритми, ітератори, об’єкти-функції, адаптери та алокатори.
8.2.8.1. Контейнери
У STL контейнери — це об’єкти, в яких можна розмістити набори інших об’єктів. Розрізняють дві категорії контейнерів: контейнери послідовностей та впорядковані асоціативні контейнери.
Контейнери послідовностей
Контейнери послідовностей організують набори об’єктів однакового типу Т у строго лінійні послідовності. У STL визначені такі контейнерні типи:
Т а[n], тобто звичайні типи масивів мови С++, які забезпечують вільний доступ до послідовності фіксованої довжини n (вільний доступ означає, що час доступу до і-го елемента сталий, тобто не залежить від і);
vector < T > забезпечує вільний доступ до послідовності змінної довжини зі сталим часом приписування та вилучення елементів в кінці послідовності;
deque < T > забезпечує вільний доступ до послідовностей змінної довжини зі сталим часом приписування та вилучення елементів у кінці послідовності;
list < T > забезпечує лінійний за часом доступ до послідовності змінної довжини (О(n), де n — поточна довжина послідовності), при цьому час приписування та вилучення елементів у будь-якому місці послідовності сталий.
Може виявитися дивним, що до цього списку включені масиви, але це пов’язано з тим, що всі параметричні алгоритми STL розроблені так, щоб забезпечити роботу з масивами в такий самий спосіб, як вони працюють з іншими видами послідовностей.
Раніше було наведено приклади використання параметричного алгоритму reverse. Ще один випадок, коли багато алгоритмів STL працюють зі стандартними типами С++, подають потоки, визначені в стандартній бібліотеці iostream мови С++; багато алгоритмів можуть вводити дані з потоку вводу та виводити їх у потоки виводу.
Крім того, контейнер забезпечує один чи більше способів обходу об’єктів, які входять до набору через інші об’єкти і називаються ітераторами. При цьому для всіх контейнерів можливий обхід його об’єктів у порядку їх слідування в контейнері.
Приклад 8.2. Параметричний алгоритм reverse для списку.
#include <iostream.h>
#include <algo.h>
#include <list.h>
#include <assert.h>
list<char> lst(char* s)
//Перетворює рядок s до структури list<char>
//(порожній символ, який закінчує рядок до структури
//не включається).
{
list<char> x;
while (*s!=`\0’)
x.push_back(*s++);
returu x;
}
int main ()
{
cout << «Demonstreting generic reverse algorithm on a list.»<<end1;
list <char> list1 = lst(«mark twain»);
reverse(list1.begin(),list1.end());
assert (list1 == lst («niawt kram»));
}
Аналогічний приклад можна навести і для дека. Загалом, вектори, списки та деки не в усіх випадках взаємозамінні, але в розглянутому прикладі кожний із контейнерів працює однаково добре. Це пов’язано з тим, що функції-члени push-back (), begin() та end() мають однаковий абстрактний зміст, хоч і реалізуються по-різному: вектори подаються за допомогою масивів, списки подаються через вузли з двома зав’язками (структури, які мають одне інформаційне поле, та два покажчики: на попередній та на наступний елементи списку), а деки реалізуються за допомогою дворівневої структури масивів. Для користування має бути зрозумілим, що для різних контейнерів параметрична функція, загалом, має різну продуктивність. У розглядуваному випадку ця різниця у продуктивності незначна, але в інших випадках, коли обробляються довші послідовності, вибір правильного контейнера може забезпечити істотніший виграш у продуктивності.
