45. Последовательные контейнеры: vector, list, deque.
Класс векторов STL — это класс шаблона контейнеров последовательностей для хранения элементов заданного типа в линейном порядке и быстрого произвольного доступа к любому элементу. Он является наиболее подходящим типом контейнера для последовательности, когда на первом месте стоит производительность произвольного доступа.
Синтаксис
template <class Type, class Allocator = allocator<Type>>
class vector
Примеры
template<
class T,
class Allocator = std::allocator<T>
> class vector;
std::vector — последовательный контейнер, инкапсулирующий массивы переменного размера.
namespace pmr {
template <class T>
using vector = std::vector<T, std::polymorphic_allocator<T>>;
}
std::pmr::vector псевдоним шаблона, использующего polymorphic allocator
Элементы хранятся непрерывно, а значит доступны не только через итераторы, но и через смещения, добавляемые к указателям на элементы (data() (std::vector::data - Возвращает указатель на базовый массив, выступающей в качестве элемента хранения. Указатель таков, что диапазон [data(); data() + size()) всегда действительный, даже если контейнер пуст. ) или же, для непустых массивов, — &vect[0]). Это означает, что указатель на элемент вектора может передаваться в любую функцию, ожидающую указатель на элемент массива.
Хранилище вектора обрабатывается автоматически, расширяясь и сужаясь по мере необходимости. Векторы обычно занимают больше места, чем статические массивы, поскольку некоторое количество памяти выделяется про запас на обработку будущего роста. Таким образом, память для вектора требуется выделять не при каждой вставке элемента, а только после исчерпания резервов. Общий объём выделенной памяти можно получить с помощью функции capacity(). Резервная память может быть возвращена системе через вызов shrink_to_fit().
Перераспределения обычно являются дорогостоящими операциями в плане производительности. Функция reserve() может использоваться для предварительного выделения памяти и устранения перераспределений, если заранее известно количество элементов.
Сложность (эффективность) обычных операций над векторами следующая:
Произвольный доступ — постоянная O(1)
Вставка и удаление элементов в конце — амортизированная постоянная O(1)
Вставка и удаление элементов — линейная по расстоянию до конца вектора O(n)
Функции-члены | |
---|---|
(конструктор) | Создаёт vector |
(деструктор) | Уничтожает vector |
operator= | Задаёт значения в контейнере |
assign | Задаёт значения в контейнере |
get_allocator | Возвращает связанный аллокатор |
Доступ к элементам | |
at | Предоставляет доступ к указанному элементу с проверкой индекса |
operator[] | Предоставляет доступ к указанному элементу |
front | Предоставляет доступ к первому элементу |
back | Предоставляет доступ к последнему элементу |
data | Предоставляет прямой доступ к внутреннему содержимому |
Итераторы | |
begin cbegin | Возвращает итератор на первый элемент |
end cend | Возвращает итератор на элемент, следующий за последним |
rbegin crbegin | Возвращает обратный итератор на первый элемент |
rend crend | Возвращает обратный итератор на элемент, следующий за последним |
Вместимость | |
empty | Проверяет отсутствие элементов в контейнере |
size | Возвращает количество элементов в контейнере |
max_size | Возвращает максимально допустимое количество элементов в контейнере |
reserve | Зарезервировать память |
capacity | Возвращает количество элементов, которые могут одновременно храниться в выделенной области памяти |
shrink_to_fit | Уменьшает использование памяти, высвобождая неиспользуемую |
Модификаторы | |
clear | Очищает контейнер |
insert | Вставляет элементы |
emplace | Конструирует элементы "на месте" и вставляет их начиная с заданной позиции pos |
erase | Удаляет последний элемент |
push_back | Добавляет элемент в конец |
emplace_back | Конструирует элементы "на месте" в конце контейнера |
pop_back | Удаляет последний элемент |
resize | Изменяет количество хранимых элементов |
swap | Обменивает содержимое |
Пример
#include <iostream>
#include <vector>
int main ( ) {
// Создание вектора, содержащего целые числа
std::vector<int> v = {7, 5, 16, 8};
// Добавление ещё двух целых чисел в вектор
v.push_back(25);
v.push_back(13);
// Проход по вектору с выводом значений
for ( int n : v ) {
std::cout << n << '\n';
}
}
Прочая инфа здесь - http://ru.cppreference.com/w/cpp/container/vector https://msdn.microsoft.com/ru-ru/library/9xd04bzs.aspx
Класс списка STL — это класс шаблона контейнеров последовательностей для хранения элементов заданного типа в линейном порядке и быстрого произвольного доступа к любому элементу. Он является наиболее подходящим типом контейнера для последовательности, когда на первом месте стоит производительность произвольного доступа.
Синтаксис
template <class Type, class Allocator= allocator<Type>>
class list
Список представляет собой контейнер, который поддерживает быструю вставку и удаление элементов из любой позиции в контейнере. Быстрый произвольный доступ не поддерживается. Он реализован в виде двусвязного списка. В отличие от std::forward_list(Forward list - контейнер, предоставляющий механизм вставки и удаления элементов из контейнера. Быстрый произвольный доступ не поддерживается. Реализован в виде однонаправленного списка и не имеет никаких накладных расходов по сравнению с аналогичной реализацией в C.) этот контейнер обеспечивает возможность двунаправленного итерирования, являясь при этом менее эффективным в отношении используемой памяти.
Функции-члены | |
---|---|
(конструктор) | Создаёт list |
(деструктор) | Уничтожает list |
operator= | Задаёт значения в контейнере |
assign | Задаёт значения в контейнере |
get_allocator | Возвращает связанный аллокатор |
Доступ к элементам | |
front | Предоставляет доступ к первому элементу |
back | Предоставляет доступ к последнему элементу |
Итераторы | |
begin cbegin | Возвращает итератор на первый элемент |
end cend | Возвращает итератор на элемент, следующий за последним |
rbegin crbegin | Возвращает обратный итератор на первый элемент |
rend crend | Возвращает обратный итератор на элемент, следующий за последним |
Вместимость | |
empty | Проверяет отсутствие элементов в контейнере |
size | Возвращает количество элементов в контейнере |
max_size | Возвращает максимально допустимое количество элементов в контейнере |
Модификаторы | |
clear | Очищает контейнер |
insert | Вставляет элементы |
emplace | Конструирует элементы "на месте" и вставляет их начиная с заданной позиции pos |
erase | Удаляет последний элемент |
push_back | Добавляет элемент в конец |
emplace_back | Конструирует элементы "на месте" в конце контейнера |
pop_back | Удаляет последний элемент |
push_front | вставляет элементы в начало списка |
emplace_front | конструирует элементы "на месте" в начало списка |
pop_front | удаляет первый элемент |
resize | Изменяет количество хранимых элементов |
swap | Обменивает содержимое |
Операции | |
merge | слияние двух отсортированных списков |
splice | перемещает элементы из другого list |
remove remove_if | удаляет элементы, удовлетворяющие определенным критериям |
reverse | изменяет порядок элементов |
unique | удаляются последовательно повторяющихся элементов |
sort | сортирует элементы |
Пример
/ list_clear.cpp
// compile with: /EHsc
#include <list>
#include <iostream>
int main() {
using namespace std;
list <int> c1;
c1.push_back( 10 );
c1.push_back( 20 );
c1.push_back( 30 );
cout << "The size of the list is initially " << c1.size( ) << endl;
c1.clear( );
cout << "The size of list after clearing is " << c1.size( ) << endl;
}
Прочая инфа здесь - http://ru.cppreference.com/w/cpp/container/list https://msdn.microsoft.com/ru-ru/library/802d66bt.aspx
Класс deque
Упорядочивает элементы заданного типа в линейном порядке и, подобно векторам, обеспечивает быстрый произвольный доступ к любому элементу и эффективную вставку и удаление в конце контейнера. Однако в отличие от объекта vector класс deque также поддерживает эффективную вставку и удаление в передней части контейнера.
Синтаксис
template <class Type,
class Allocator =allocator<Type>>
class deque
std::deque (двусторонняя очередь) представляет собой последовательный индексированный контейнер, который позволяет быстро вставлять и удалять элементы с начала и с конца. Кроме того, вставка и удаление с обоих концов двусторонней очереди оставляет действительными указатели и ссылки на остальные элементы.
В отличие от std::vector, элементы дека не хранятся непрерывно: обычно реализован с помощью набора выделенных массивов фиксированного размера.
Хранилище дека обрабатывается автоматически, расширяясь и сужаясь по мере необходимости. Расширение дека дешевле, чем расширение std::vector, потому что оно не требует копирования существующих элементов в новый участок памяти.
Сложность (производительность) стандартных операций над двусторонней очередью следующая:
- Произвольный доступ - постоянная O(1)
- Вставка и удаление элементов с начала и с конца - амортизированная постоянная O(1)
- Вставка и удаление элементов - линейная O(n)
Функции-члены | |
---|---|
(конструктор) | Создаёт deque |
(деструктор) | Уничтожает deque |
operator= | Задаёт значения в контейнере |
assign | Задаёт значения в контейнере |
get_allocator | Возвращает связанный аллокатор |
Доступ к элементам | |
at | Предоставляет доступ к указанному элементу с проверкой индекса |
operator[] | Предоставляет доступ к указанному элементу |
front | Предоставляет доступ к первому элементу |
back | Предоставляет доступ к последнему элементу |
Итераторы | |
begin cbegin | Возвращает итератор на первый элемент |
end cend | Возвращает итератор на элемент, следующий за последним |
rbegin crbegin | Возвращает обратный итератор на первый элемент |
rend crend | Возвращает обратный итератор на элемент, следующий за последним |
Вместимость | |
empty | Проверяет отсутствие элементов в контейнере |
size | Возвращает количество элементов в контейнере |
max_size | Возвращает максимально допустимое количество элементов в контейнере |
shrink_to_fit | |
Модификаторы | |
clear | Очищает контейнер |
insert | Вставляет элементы |
emplace | Конструирует элементы "на месте" и вставляет их начиная с заданной позиции pos |
erase | Удаляет последний элемент |
push_back | Добавляет элемент в конец |
emplace_back | Конструирует элементы "на месте" в конце контейнера |
pop_back | Удаляет последний элемент |
push_front | вставляет элементы в начало списка |
emplace_front | конструирует элементы "на месте" в начало списка |
pop_front | удаляет первый элемент |
resize | Изменяет количество хранимых элементов |
swap | Обменивает содержимое |
Пример
// deque_assign.cpp
// compile with: /EHsc
#include <deque>
#include <iostream>
#include <initializer_list>
int main()
{
using namespace std;
deque <int> c1, c2;
deque <int>::const_iterator cIter;
c1.push_back(10);
c1.push_back(20);
c1.push_back(30);
c2.push_back(40);
c2.push_back(50);
c2.push_back(60);
deque<int> d1{ 1, 2, 3, 4 };
initializer_list<int> iList{ 5, 6, 7, 8 };
d1.assign(iList);
cout << "d1 = ";
for (int i : d1)
cout << i;
cout << endl;
cout << "c1 =";
for (int i : c1)
cout << i;
cout << endl;
c1.assign(++c2.begin(), c2.end());
cout << "c1 =";
for (int i : c1)
cout << i;
cout << endl;
c1.assign(7, 4);
cout << "c1 =";
for (int i : c1)
cout << i;
cout << endl;
}
Прочая инфа здесь - http://ru.cppreference.com/w/cpp/container/deque https://msdn.microsoft.com/ru-ru/library/22a9t119.aspx