Умные указатели

 
0
 
C++
ava
Tiarwe | 25.01.2013, 19:37
Здравствуйте! Изучаю умные указатели и что-то совсем запутался... Вначале опишу, что мне нужно.
Есть класс Book и vector из указателей на эти книги. Вот захотелось мне, чтобы это были не обычные указатели, а умные...
1) В чём разница между shared_ptr и auto_ptr? Правильно ли я понимаю, что при auto_ptr на объект может ссылаться лишь один указатель, в то время как при shared_ptr - множество (т.к. идёт подсчёт ссылок)? При этом, если auto_ptr перестаёт указывать на объект, то он уничтожается? Ровно как и shred_ptr, когда кол-во ссылок равно 0?
2) Вернёмся к вектору. Пускай в нём 1000 умных указателей на объекты. И мне например захотелось удалить 200 объектов... Т.е. мне надо всего-лишь удалить указатели из вектора и больше ни о чём не беспокоиться?
3) Или на примере игры... есть Object и вектор из 100 Target'ов. Object имеет в себе указатель на один из Target'ов... Эти самые 100 Target'ов должны быть именно shared_ptr, т.к. на них ещё могут ссылаться из вне?
В общем, каша в голове  smile 
Kommentare (18)
ava
mes | 25.01.2013, 18:47 #
если речь о векторе про ауто_птр можно сразу забыть...

Цитата (Tiarwe @  25.1.2013,  17:37 findReferencedText)
 Правильно ли я понимаю, что при auto_ptr на объект может ссылаться лишь один указатель,

не совсем..  ауто_птр владеет одним обьектом, при копировании передаёт все права с обьектом другому ауто_птр, а при разрушении удаляет обьект коим владеет..
ava
bsa | 25.01.2013, 23:12 #
Tiarwe, auto_ptr такая своеобразная штука, что лучше ей не пользоваться. Если не знаешь для чего она нужна. Сейчас ее имеет смысл использовать только для контроля времени жизни динамического объекта по типу автоматических. Хотя для этого есть (в boost) более подходящая штука - scoped_ptr. Которая ведет себя более предсказуемо без чтения документации.
ava
EvilsInterrupt | 26.01.2013, 16:14 #
Tiarwe, Читай книгу Джосьютиса "Стандартная библиотека C++". Там описан std::auto_ptr во всех красках, описаны его ограничения и его возможности, а также нюансы. После его описания в это книге приведен пример кода умного указателя с подсчетом ссылок.
ava
EvilsInterrupt | 26.01.2013, 23:43 #
Tiarwe,
Я бы юзал не вектор указателей, а список указателей. Посмотрите в сторону других контейнеров отличных от std::vector, к примеру std::list. Во внутренней реализации этого контейнера как правило участвуют указатели( не те что хранятся в этом контейнере, в контейнере может храниться любой тип хоть SuperPuperMatreshka). Обратите внимание на слово "complexity" вот список STL контейнеров

später ergänzt:
А вот другая для распечатывания на стену
ava
borisbn | 27.01.2013, 18:01 #
EvilsInterrupt, в чём сермяжная правда отказа от вектора? Если уж так любишь ссылаться на книги, почему не привести цитату из Майерса:
Цитата
Если не знаете какой контейнер выбрать - берите вектор

За точность цитаты не ручаюсь, за смысл - да
ava
mes | 27.01.2013, 19:07 #
Цитата (EvilsInterrupt @  26.1.2013,  22:43 findReferencedText)
 Во внутренней реализации этого контейнера как правило участвуют указатели( не те что хранятся в этом контейнере, в контейнере может храниться любой тип хоть SuperPuperMatreshka). 

 smile  smile  smile 
ava
Dem_max | 27.01.2013, 19:53 #
Почитай тут все расжевано
http://www.rsdn.ru/article/cpp/smartptr.xml
ava
EvilsInterrupt | 28.01.2013, 01:16 #
Цитата (borisbn @  27.1.2013,  19:01 findReferencedText)
Если не знаете какой контейнер выбрать - берите вектор

Это если не знать! Вектор как правило имеет смысл выбирать если нужно непрерывную область, так сказать C-стайл, сейчас его вроде как std::array может заменить в этом, судя по описанию на cppreference.

Более того в постановке задачи:
Цитата


Есть класс Book и vector из указателей на эти книги


и:
Цитата


Пускай в нём 1000 умных указателей на объекты



Ни одного намека на то что человеку нажно хранить книги в С-подобном виде, т.е. последовательно в файле. Зато указано 1000 !!!! Т.е. человек предполагает что ему надо будет достаточно часто вставлять. Другое из постановки задачи:
Цитата


И мне например захотелось удалить 200 объектов...



Вы все еще уверены в векторе? Удалить 200 штук, добавить 1000...
ava
borisbn | 28.01.2013, 09:16 #
Цитата (EvilsInterrupt @  28.1.2013,  01:16 findReferencedText)
 Вектор как правило имеет смысл выбирать если нужно непрерывную область, так сказать C-стайл, сейчас его вроде как std::array может заменить в этом

1) то, что в векторе память непрерывная - спорить глупо, но его чаще выбирают по другим причинам (правда, являющимся следствием непрерывности) - random acces за постоянное время и т.п.
2) std::array заменил массивы типа
T array[ 100 ];

а ни разу не вектор

Цитата (EvilsInterrupt @  28.1.2013,  01:16 findReferencedText)
Вы все еще уверены в векторе? Удалить 200 штук, добавить 1000... 

По поводу добавить - уверен:
http://liveworkspace.org/code/2eY9uN$9
По поводу удалить - подумай во над чем: прежде чем удалить элемент из контейнера его нужно там найти. Тест поиска элемента в векторе и в листе написать ? или и так понятно ?
ava
EvilsInterrupt | 28.01.2013, 10:37 #
borisbn,
Вы правы! Спасибо за аргументацию, которую можно "пощупать" и "потрогать". Нельзя мне в 2 ночи посты писать, каюсь! ;)
ava
mes | 28.01.2013, 19:49 #
Цитата


По поводу добавить - уверен:


и это еще .reserve не использован ))

справедливости ради надо отметить, большая разница, вставлять в конец или в начало.. 
ava
bsa | 29.01.2013, 14:19 #
Цитата (mes @  28.1.2013,  20:49 findReferencedText)
справедливости ради надо отметить, большая разница, вставлять в конец или в начало.. 

Если честно меня удивляет, почему разработчики STL не сделали такую простую штуку, как возможность добавлять в начало вектора с такой же сложностью, как и в конец. Реализуется это всего лишь одним дополнительным указателем внутри класса и тройкой методов (reserve_front(), push_front(), pop_front()).
ava
baldina | 29.01.2013, 14:44 #
Цитата (bsa @  29.1.2013,  14:19 findReferencedText)
Реализуется это всего лишь одним дополнительным указателем внутри класса

vector должен быть непрерывным от &v[0]

später ergänzt:
есть же deque<>, тут вам и такая же временная сложность, и добавление в начало.
лишь непрерывность не гарантирована
ava
bsa | 29.01.2013, 15:43 #
Цитата (baldina @  29.1.2013,  15:44 findReferencedText)
vector должен быть непрерывным от &v[0]
А кто мешает? Просто сейчас добавление в начало всегда приводит к сдвигу всех элементов, а в случае с дополнительным указателем - сдвигалось бы только начало массива (если резерв перед данными есть):
template<class Type, class Allocator>
class vector
{
private:
   Type *area_beg_; //нужно добавить
   Type *data_beg_; //остальные три уже есть
   Type *data_end_;
   Type *area_end_;
};
главное условие: area_beg_ <= data_beg_ <= data_end_ <= area_end_
Если data_end_ == data_beg_, то вектор пуст
Если area_end_ == area_beg_, то вектор не имеет резерва (и пуст).
Если area_beg_ < data_beg_, то у вектора есть резерв перед началом
Если data_end_ < area_end_, то у вектора есть резерв после конца

Таким образом, сложность добавления в начало была бы равна сложности добавления в конец.
ava
baldina | 29.01.2013, 18:00 #
хитрО  smile 
ava
bsa | 29.01.2013, 19:51 #
Да ничего хитрого. Оптимизация добавления в конец именно так и сделана. Почему бы не добавить еще и оптимизацию добавления в начало? Не думаю, что еще один указатель сильно много займет ресурсов. А вот выигрыш по скорости добавления в начало был бы ощутимым.
ava
volatile | 29.01.2013, 23:55 #
Цитата (bsa @  29.1.2013,  19:51 findReferencedText)
Почему бы не добавить еще и оптимизацию добавления в начало? 

Думаю что вектор не проектировался как контейнер с оптимизацией добавления в конец. Просто это получилось само-собой.
А оптимизация добавления в начало, сама собой не получилась  smile,  ну и делать ее специально никто не стал, так как для этого есть дек.

Если вы считаете что часто нужно такое, можно сделать свой адаптер к вектору (думаю не много кода будет).
Хотя честно, говоря не вижу серьезных причин, почему бы в таком случае, просто не использовать дек...
ava
mes | 30.01.2013, 08:43 #
Цитата (volatile @  29.1.2013,  22:55 findReferencedText)
А оптимизация добавления в начало, сама собой не получилась

 smile,  чтоб делать оптимизацию вставки вперед посредством резерва, нужно иметь без оного резерва  вставку вперед такой же сложности, как вставка назад...

später ergänzt:
 smile сам непонял, что сказал...  smile 
Registrieren Sie sich oder melden Sie sich an, um schreiben zu können.
Unternehmen des Tages
Вы также можете добавить свою фирму в каталог IT-фирм, и публиковать статьи, новости, вакансии и другую информацию от имени фирмы.
Подробнее
Mitwirkende
advanced
Absenden