Скотт Мейерс - Эффективное использование STL

Тут можно читать онлайн Скотт Мейерс - Эффективное использование STL - бесплатно полную версию книги (целиком) без сокращений. Жанр: comp-programming, издательство Питер, год 2002. Здесь Вы можете читать полную версию (весь текст) онлайн без регистрации и SMS на сайте лучшей интернет библиотеки ЛибКинг или прочесть краткое содержание (суть), предисловие и аннотацию. Так же сможете купить и скачать торрент в электронном формате fb2, найти и слушать аудиокнигу на русском языке или узнать сколько частей в серии и всего страниц в публикации. Читателям доступно смотреть обложку, картинки, описание и отзывы (комментарии) о произведении.
  • Название:
    Эффективное использование STL
  • Автор:
  • Жанр:
  • Издательство:
    Питер
  • Год:
    2002
  • Город:
    СПб.
  • ISBN:
    ISBN 5-94723-382-7
  • Рейтинг:
    4/5. Голосов: 91
  • Избранное:
    Добавить в избранное
  • Отзывы:
  • Ваша оценка:
    • 80
    • 1
    • 2
    • 3
    • 4
    • 5

Скотт Мейерс - Эффективное использование STL краткое содержание

Эффективное использование STL - описание и краткое содержание, автор Скотт Мейерс, читайте бесплатно онлайн на сайте электронной библиотеки LibKing.Ru

В этой книге известный автор Скотт Мейерс раскрывает секреты настоящих мастеров, позволяющие добиться максимальной эффективности при работе с библиотекой STL.

Во многих книгах описываются возможности STL, но только в этой рассказано о том, как работать с этой библиотекой. Каждый из 50 советов книги подкреплен анализом и убедительными примерами, поэтому читатель не только узнает, как решать ту или иную задачу, но и когда следует выбирать то или иное решение — и почему именно такое.

Эффективное использование STL - читать онлайн бесплатно полную версию (весь текст целиком)

Эффективное использование STL - читать книгу онлайн бесплатно, автор Скотт Мейерс
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

Как только вы поймете, что алгоритм remove не может «по-настоящему» удалять объекты из контейнера, применение его в сочетании с erase войдет в привычку. Не забывайте, что remove — не единственный алгоритм, к которому относится это замечание. Существуют два других remove-подобных алгоритма: remove_if и unique.

Сходство между remove и remove_if настолько прямолинейно, что я не буду на нем останавливаться, но алгоритм unique тоже похож на remove. Он предназначен для удаления смежных повторяющихся значений из интервала без доступа к контейнеру, содержащему элементы интервала. Следовательно, если вы хотите действительно удалить элементы из контейнера, вызов unique должен сопровождаться парным вызовом erase. В контейнере list также предусмотрена функция unique, производящая фактическое удаление смежных дубликатов. По эффективности она превосходит связку erase-unique.

Совет 33. Будьте внимательны при использовании remove-подобных алгоритмов с контейнерами указателей

Предположим, мы динамически создаем ряд объектов Widget и сохраняем полученные указатели в векторе:

class Widget {

public:

bool isCertified() const; // Функция сертификации объектов Widget

vector v; // Создать вектор и заполнить его указателями

v.push_back(new Widget); // на динамически созданные объекты Widget

Поработав с v в течение некоторого времени, вы решаете избавиться от объектов Widget, не сертифицированных функцией Widget, поскольку они вам не нужны. С учетом рекомендаций, приведенных в совете 43 (по возможности использовать алгоритмы вместо циклов), и того, что говорилось в совете 32 о связи remove и erase, возникает естественное желание использовать идиому erase-remove, хотя в данном случае используется алгоритм remove_if:

v.erase(remove_if(v.begin(), v.end(),// Удалить указатели на объекты

not1(mem_fun(&Widget::isCertified))). //Widget, непрошедшие v.end());// сертификацию.

// Информация о mem_fun

// приведена в совете 41.

Внезапно у вас возникает беспокойство по поводу вызова erase, поскольку вам смутно припоминается совет 7 — уничтожение указателя в контейнере не приводит к удалению объекта, на который он ссылается. Беспокойство вполне оправданное, но в этом случае оно запоздало. Вполне возможно, что к моменту вызова erase утечка ресурсов уже произошла. Прежде чем беспокоиться о вызове erase, стоит обратить внимание на remove_if.

Допустим, перед вызовом remove_if вектор v имеет следующий вид:

После вызова removeif вектор выглядит примерно так с итератором возвращаемым - фото 14

После вызова remove_if вектор выглядит примерно так (с итератором, возвращаемым при вызове remove_if):

Если подобное превращение кажется непонятным обратитесь к совету 32 где - фото 15

Если подобное превращение кажется непонятным, обратитесь к совету 32, где подробно описано, что происходит при вызове remove (в данном случае — remove_if).

Причина утечки ресурсов очевидна. «Удаленные» указатели на объекты В и С были перезаписаны «оставшимися» указателями. На два объекта Widget не существует ни одного указателя, они никогда не будут удалены, а занимаемая ими память расходуется впустую.

После выполнения remove_if и erase ситуация выглядит следующим образом:

Здесь утечка ресурсов становится особенно очевидной и к настоящему моменту вам - фото 16

Здесь утечка ресурсов становится особенно очевидной, и к настоящему моменту вам должно быть ясно, почему алгоритмы remove и его аналоги (remove_if и unique) не рекомендуется вызывать для контейнеров, содержащих указатели на динамически выделенную память. Во многих случаях разумной альтернативой является алгоритм partition (см. совет 31).

Если без removeникак не обойтись, одно из решений проблемы заключается в освобождении указателей на несертифицированные объекты и присваивании им null перед применением идиомы erase-removeс последующим удалением из контейнера всех null-указателей:

void delAndNullifyUncertified(Widget*& pWidget) {

if(!pWidget()->isCertified()){ //Если объект *pWidget не сертифицирован,

delete pWidget; //удалить указатель

pWidget=0;//и присвоить ему null

}

for_each(v.begin(),.v.end(), // Удалить и обнулить все указатели на

delAndNullifyUncertified); // все указатели на объекты, не прошедшие

v.erase(remove(v.begin(),v.end(), // Удалить из v указатели null;

static_cast(0)), //0 преобразуется в указатель, чтобы С++

v.end()); //правильно определял тип третьего параметра

Приведенное решение предполагает, что вектор не содержит null-указателей, которые бы требовалось сохранить. В противном случае вам, вероятно, придется написать собственный цикл, который будет удалять указатели в процессе перебора. Удаление элементов из контейнера в процессе перебора связано с некоторыми тонкостями, поэтому перед реализацией этого решения желательно прочитать совет 9.

Если контейнер указателей заменяется контейнером умных указателей с подсчетом ссылок, то все трудности, связанные с remove,исчезают, а идиома erase-removeможет использоваться непосредственно:

template class RCSP{..}; // RCSP = "Reference Counting Smart Pointer"

typedef RCSP RCSPW; // RCSPW = "RCSP to Widget"

vector v;

v.push_back(RCSPW(new Widget)):

v. erase(remove_if(v.begin() .v.end(),

not1(mem_fun(&Widget::isCertified))).

v.end()):

Чтобы этот фрагмент работал, тип умного указателя (например, RCSP >) должен преобразовываться в соответствующий тип встроенного указателя (например Widget *). Дело в том, что контейнер содержит умные указатели, но вызываемая функция (например Widget :: i sCe rti fed)работает только со встроенными указателями. Если автоматическое преобразование невозможно, компилятор выдаст сообщение об ошибке.

Если в вашем программном инструментарии отсутствует шаблон умного указателя с подсчетом ссылок, попробуйте шаблон shared_ptr из библиотеки Boost. Начальные сведения о Boost приведены в совете 50.

Независимо от того, какая методика будет выбрана для работы с контейнерами динамически созданных указателей — умные указатели с подсчетом ссылок, ручное удаление и обнуление указателей перед вызовом remove-подобных алгоритмов или другой способ вашего собственного изобретения — главная тема данного совета остается актуальной: будьте внимательны при использовании remove-подобных алгоритмов с контейнерами указателей. Забывая об этой рекомендации, вы своими руками создаете предпосылки для утечки ресурсов.

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать


Скотт Мейерс читать все книги автора по порядку

Скотт Мейерс - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки LibKing.




Эффективное использование STL отзывы


Отзывы читателей о книге Эффективное использование STL, автор: Скотт Мейерс. Читайте комментарии и мнения людей о произведении.


Понравилась книга? Поделитесь впечатлениями - оставьте Ваш отзыв или расскажите друзьям

Напишите свой комментарий
x