bimap - пары (a, b), по элементу можно найти второй
lru-cache - мапа с ограниченным числом элементов (самое старое удаляет)
Почему например просто 2 мапы плохо? Одни и те же данные хранятся и в самом объекте, и как ключи мапы, если мы добавили в одну мапу, а при добавлении во вторую произошло исключение, то объект будет лишь в 1 мапе
Есть годная штука, которой даешь объект и говоришь, какие индексы хочешь
boost::multi_index - контейнер с определенным количеством индексов
Позволяет искать (в контейнере?) не только по искомому типу (н-р вместо string
передавать const char*
)
С помощью него же в массиве <ключ, значение> искать только по ключу (например в мапу надобавляли элементов, а потом только ищем)
Есть в std::lowel_bound
, std::set
, std:::map
Много указателей - объект один
Все аккуратно удаляется
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"><</span><span class="token keyword">typename</span> D<span class="token operator">></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 аллокация
Допустим хотим хранить кэш картинок
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
struct B {}; struct D : B {}
shared_prt<B> b; shared_prt<D> d = static_pointer_cast<D>(b); (?)
Для shared_ptr