Upload
cs-center
View
1.069
Download
10
Embed Size (px)
DESCRIPTION
- Гарантии и требования к элементам - Контейнеры и адаптеры
Citation preview
Лекция 1. Стандартная
библиотека
Контейнеры
Valery Lesin. C++ In-Depth, 2014
Стандартная библиотека
• Минимальный полный набор возможностей для обеспечения базовых потребностейю.
• Если что-то содержит, должна реализовывать лучшим образом (стать стандартом де-факто).
• Алгоритмически эффективна.
• Расширяема (может использовать как стандартные, так и пользовательские типы).
Valery Lesin. C++ In-Depth, 2014
Состав стандартной библиотеки• Включает в себя CRT (C Run Time Library) и
STL (Standard Template Library)
• Содержит
– контейнеры: vector, list, map, unordered_set, …
– утилиты: пары, аллокаторы, …
– итераторы
– алгоритмы: for_each, sort, lower_bound, …
– диагностика: assert, exception, …
– строки: string, wstring
– ввод/вывод: потоки cout, cin; printf, …
Valery Lesin. C++ In-Depth, 2014
Состав стандартной библиотеки (2)
• Содержит (продолжение):
– локализацию
– поддержку языка: numeric_limits, typeinfo, new/delete
– числовые операции: complex, <cmath>
• Для хидера <name.h> из CRT есть хидер<cname> с теми же объявлениями в пространстве имен std
• Используйте только стандартные хидерадля объявления стандартных типов и функций
Valery Lesin. C++ In-Depth, 2014
Контейнеры STL
• Реализуют стандартные операции с соответствующими именами и смыслом.
• Однородны – все хранимые объекты одного типа. Но могут хранить указатели (желательно умные) на полиморфные.
• Требуют минимум от хранимого типа.
• Универсально итерируемы.
• Можно настроить (аллокаторы, компараторы).
Valery Lesin. C++ In-Depth, 2014
Типы контейнеров
• Списочные: array, vector, list, deque, forward_list
• Ассоциативные: map, set, multiset,multimap
• Unordered: unordered_map,
unordered_multiset, …
• Адапторы: stack, queue, priority_queue
• «Почти» контейнеры: bitset, string, …
Valery Lesin. C++ In-Depth, 2014
Контейнер vector
Valery Lesin. C++ In-Depth, 2014
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template<class T, class Allocator = std::allocator<T>>
class vector
{
typedef typename T value_type;
typedef Allocator allocator_type;
typedef typename Allocator::size_type size_type;
typedef typename Allocator::difference_type difference_type;
typedef typename Allocator::pointer pointer;
typedef typename Allocator::const_pointer const_pointer;
typedef typename Allocator::reference reference;
typedef typename Allocator::const_reference const_reference;
typedef impl-defined iterator;
typedef impl-defined const_iterator;
typedef reverse_iterator<iterator> reverse_iterator;
typedef reverse_iterator<const_iterator> const_reverse_iterator;
// ...
};
Valery Lesin. C++ In-Depth, 2014
Итераторы1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
template<class T, class Allocator = std::allocator<T>>
class vector
{
// ...
iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
reverse_iterator rend();
const_reverse_iterator rend() const;
const_iterator cbegin() const;
const_iterator cend () const;
const_reverse_iterator crbegin() const;
const_reverse_iterator crend () const;
// ...
};
Итераторы
• Типы итераторов: Output; Input, Forward,
Bidirectional, RandomAccess
Valery Lesin. C++ In-Depth, 2014
Item 0 Item 1 Item 2 Item 3
end
cend
begin
cbegin
it
reverse it
1.
2.
&(*reverse_it) != &(*(revese_it.base()));
&(*reverse_it) == &(*(std::prev(revese_it).base()));
По вектору в обратном направлении
Valery Lesin. C++ In-Depth, 2014
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
// forward
for (size_t i = 0; i < v.size(); ++i)
cout << v[i] << endl;
// naive backward (hmmm, with suprises)
for (size_t i = v.size() - 1; i >= 0; ++i)
cout << v[i] << endl;
// correct
for (vector<int>::const_reverse_iterator it = v.rbegin();
it != v.rend(); ++it)
cout << *it << endl;
// correct and tiny
for (auto it = v.rbegin(); it != v.rend(); ++it)
cout << *it << endl;
// range-based for
for (auto item : reverse(v))
cout << item << endl;
Как устроен вектор?
• Вектор – динамический массив.
• При нехватке места увеличивается ~ в 2 раза
• Трудоемкость вставки в конец (!) –амортизированная O(1)
Valery Lesin. C++ In-Depth, 2014
Size
Capacity
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
bool empty() const;
size_type size () const;
void resize(size_type size, T val = T());
size_type capacity() const;
void reserve (size_type size);
void clear ();
void shrink_to_fit();
iterator erase (const_iterator where);
Вставка и удаление из вектора
• Функция remove и remove_if ничего не
удаляют, а лишь переносят в конец.
Valery Lesin. C++ In-Depth, 2014
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
// could be const_iterator since C++11
vector<T>::iterator from, to, where;
// random place
v.insert(where, val);
// usual erase
v.erase(from, to);
v.erase(where);
// erase items with value with 'remove' function
// or use 'remove_if' for predicate usage
v.erase(v.begin(), remove(v.begin(), v.end(), 42));
Вектор. Концевые элементы и индекс
• Вектор позволяет эффективно вставлять и удалять элементы с конца. Но (!) не сначала.
Valery Lesin. C++ In-Depth, 2014
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
void push_back(T const& value);
void push_back(T && value);
template< class... Args >
void emplace_back( Args&&... args );
void pop_back();
reference back();
const_reference back() const;
reference front();
const_reference front() const
pointer data(); // and const
reference operator[](size_type index);
reference at(size_type index);
Конструирование вектора
• Конструктор по умолчанию, копирования,
move-конструктор
• А также:
Valery Lesin. C++ In-Depth, 2014
1.
2.
3.
4.
5.
6.
7.
8.
vector<T> v0(from, to);
vector<T> v1(num, value);
// reassign already constructed vector
v0.assign(from, to);
// initializer list (since C++11)
vector<int> v2 = {1, 42, 10, 20};
Контейнер sdt::list
• Двунаправленный список
• Вставка, удаление из любого места О(1)
• Нет RandomAccess итератора, только
Bidirectional
• Полезны splice, sort
• В отличие от вектора: pop_front, push_front
Valery Lesin. C++ In-Depth, 2014
1.
2.
template<class T, class Alloc = std::allocator<T>>
class list;
Контейнер std::deque
• Есть RandomAccess итератор (возможно,
несколько менее эффективно, чем в
векторе)
• Позволяет вставлять/удалять в начало и
конец за O(1) (но не в произвольное место)
• Часто реализуется через вектор векторов
Valery Lesin. C++ In-Depth, 2014
Адаптеры
• std::stack: push, pop, top
• std::queue: push, pop, front, back
• std::priority_queue: push, pop, top,
constructor
Valery Lesin. C++ In-Depth, 2014
1.
2.
3.
4.
template<class T,
class Container = vector<T>,
class Pr = less<typename Container::value_type>>
class priority_queue;
Ассоциативные контейнеры
• Наиболее популярный – std::map
Valery Lesin. C++ In-Depth, 2014
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
template<
class Key,
class Value,
class Predicate = less<Key>,
class Alloc = allocator<pair<const Key, Value>>>
class map
{// usually, some balanced tree (e.g. red-black)
public:
typedef Key key_type;
typedef Value mapped_type;
typedef pair<const Key, Value> value_type;
typedef Predicate key_compare;
// ...
};
Итерирование map
• Итератор разыменовывается в пару. Ключ –
first, значение – second.
Valery Lesin. C++ In-Depth, 2014
1.
2.
3.
4.
5.
6.
7.
8.
map<string, size_t> marks;
for (auto it = marks.begin(); it != marks.end(); ++it)
cout << it->first << " " << it->second << endl;
//...
it->second = 5; // ok
it->first = "Vasya"; // nope, cannot change key
Поиск и вставка в map
Valery Lesin. C++ In-Depth, 2014
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
typedef std::map<string, size_t> map_t;
typedef map_t::iterator iterator;
map_t m;
// simple insert
auto it = m.find(str);
if (it != n.end())
return ...;
pair<iterator, bool> p =
m.insert(make_pair(str, 5));
// with 'hint'
auto it = m.lower_bound(str);
if (it != m.end() && it->second == str)
return ...;
m.insert(it, make_pair(str, 5));
Индексирование
• Если элемента не было в map – добавит
• Если был – оператора вернет ссылку и
произойдет замена текущего значения (в
отличие от insert)
• Оператор [] всегда неконстантный. Есть
только у map, нет у set, multiset, multimap.
Valery Lesin. C++ In-Depth, 2014
1.
2.
3.
4.
5.
6.
typedef std::map<string, size_t> map_t;
typedef map_t::iterator iterator;
map_t m;
m[str] = 5;
Удаление из map (set)
Valery Lesin. C++ In-Depth, 2014
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
m.erase(key);
m.erase(from, to);
// with predicate
for (auto it = m.begin(); it != m.end(); ++it)
{
if (predicate(*it))
m.erase(it++);
else
++it;
}
Другие ассоциативные контейнеры
• std::set – содержит только ключи
• std::multimap, std::multiset – ключи могут повторяться
• std::unordered_map/set
– используют вычисление хэшей и предикат равенства вместо предиката порядка
– вставка, удаление, поиск – амортизированная O(1)
– Требуют больше памяти, чем обычные map/set
– Есть более быстрые реализации: Google sparse/dense hash map, MCT hash map
Valery Lesin. C++ In-Depth, 2014
Спасибо за внимание!
Вопросы?
Valery Lesin. C++ In-Depth, 2014