Skip to content

Latest commit

 

History

History
87 lines (79 loc) · 12.4 KB

Lecture 02.md

File metadata and controls

87 lines (79 loc) · 12.4 KB


Multi-index containers

bimap - пары (a, b), по элементу можно найти второй
lru-cache - мапа с ограниченным числом элементов (самое старое удаляет)

Почему например просто 2 мапы плохо? Одни и те же данные хранятся и в самом объекте, и как ключи мапы, если мы добавили в одну мапу, а при добавлении во вторую произошло исключение, то объект будет лишь в 1 мапе

Есть годная штука, которой даешь объект и говоришь, какие индексы хочешь
boost::multi_index - контейнер с определенным количеством индексов

Heterogeneous lookup (гетерогенный поиск)

Позволяет искать (в контейнере?) не только по искомому типу (н-р вместо string передавать const char*)

С помощью него же в массиве <ключ, значение> искать только по ключу (например в мапу надобавляли элементов, а потом только ищем)

Есть в std::lowel_bound, std::set, std:::map

Shared_pointer

Много указателей - объект один
Все аккуратно удаляется

shared_ptr<my_type> p(new my_type);
shared_ptr<my_type> q = p;
...

Нельзя хранить счетчик в самом поинтере - будет у каждого свой
Выход - храним отдельный shared_counter и на него ссылаемся

template<typename T>
struct shared_ptr {
	T* obj;
	size_t* count;
<span class="token keyword">template</span><span class="token operator">&lt;</span><span class="token keyword">typename</span> D<span class="token operator">&gt;</span>
<span class="token function">shared_ptr</span> <span class="token punctuation">(</span>T<span class="token operator">*</span> ptr<span class="token punctuation">,</span> D deleter<span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token function">obj</span><span class="token punctuation">(</span>ptr<span class="token punctuation">)</span><span class="token punctuation">,</span> 
					<span class="token keyword">try</span> <span class="token punctuation">{</span>
		 				count <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token function">size_t</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
					<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
						<span class="token function">deleter</span><span class="token punctuation">(</span>ptr<span class="token punctuation">)</span><span class="token punctuation">;</span>
						<span class="token keyword">throw</span><span class="token punctuation">;</span>
					<span class="token punctuation">}</span>
<span class="token punctuation">{</span><span class="token punctuation">}</span>

};

my_type *t = new my_type(); shared_ptr<my_type> p(t); shared_ptr<my_type> q(t); // Очень плохо - 2 разных счетчика

deleter нужен, если мы хотим н-р вернуть объект в пулл, а не удалить его, когда все указатели удалятся


struct wheel {};

struct car { array<weel, 4> wheels; //Беда array<shared_ptr<wheel>, 4> wheels; //Норм? }

Хотим shared_ptr на wheel

Что плохого может быть? Если мы откуда-то ссылаемся на объект, то это не значит что он должен жить. Н-р удалили машину, а колесо не знает что она удалена и продолжает жить

Aliasing constructor
Выход - сделать общий счетчик у car и у wheel, а само wheel хранить внутри car

shared_ptr<car> p;
shared_ptr<wheel> q(p, &p->wheels[2]);

Идиоматическое использование shared_ptr

shared_ptr<my_type> q = make_shared<my_type>(1, 2, 3)

Такое использование не делает 2 аллокации (на counter и obj), а сделает один общий объект -> 1 аллокация

Weak_pointer

Допустим хотим хранить кэш картинок

map<string, shared_ptr<image>> cache;

Проблема - все что было загружено, не будет удалено пока существует кэш, так как shared_ptr держит объект

Хранит указатель на shared_counter
Это позволяет удалить объект до того, как будут удалены все weak_ptr (хранится еще и weak_count) (не работает при make_shared, ибо 1 аллокация, при нем будет вызван деструктор, но не будет освобождена память)

map<string, weak_pointer<image>> cache;

Позволит выгрузить из кэша картинку, с shared_ptr картинки будут в кэше до его удаления

weak_ptr<mytype> w;
w.lock() //Возвращает либо поинтер, либо 0 если объект уже удален

Для многопоточности важно, что .lock() это одна операция, что она не разделена на 2

Smart pointers + наследование

struct B {};
struct D : B {}

shared_prt<B> b; shared_prt<D> d = static_pointer_cast<D>(b); (?)

Для shared_ptr