Эффективное использование STL - [23]
>АссоцКонтейнер
>for(АссоцКонтейнер<int>::iterator i=c.begin();// Третья часть заголовка
> i!=c.end(); // цикла for пуста; i теперь
> /* пусто */) { // изменяется внутри цикла
>if (badValue(*i)) c.erase(i++);// Для удаляемых элементов
> else ++i; // передать erase текущее
>} // значение i и увеличить i.
> // Для остающихся элементов
> // просто увеличить i
Новый вариант вызова >erase
работает, поскольку выражение >i++
равно старому значению >i
, но у него имеется побочный эффект — приращение >i
. Таким образом, мы передаем старое (не увеличенное) значение >i
и увеличиваем >i
перед вызовом >erase
. Именно это нам и требовалось. Хотя это решение выглядит просто, лишь немногие программисты предложат его с первой попытки.
Пора сделать следующий шаг. Помимо простого удаления всех элементов, для которых >badValue
возвращает >true
, мы также хотим регистрировать каждую операцию удаления в журнале.
Для ассоциативных контейнеров задача решается очень просто, поскольку она требует лишь тривиальной модификации созданного цикла:
>ofstream logFile;// Файл журнала
>АссоцКонтейнер
>…
>for(АссоцКонтейнер
> i!=c.end();) { // без изменений
> if(badValue(*i)) {
> logFile<<"Erasing "<<*i<<'\n'; // Вывод в журнал
> c.erase(i++);// Удаление
>} else ++i;
>}
На этот раз хлопоты возникают с >vector
, >string
и >deque
. Использовать идиому >erase/remove
не удается, поскольку >erase
или >remove_if
нельзя заставить вывести данные в журнал. Более того, вариант с циклом >for
, только что продемонстрированный для ассоциативных контейнеров, тоже не подходит, поскольку для контейнеров >vector
, >string
и >deque
он приведет к непредсказуемым последствиям. Вспомните, что для этих контейнеров в результате вызова >erase
становятся недействительными все итераторы, указывающие на удаляемый элемент. Кроме того, недействительными становятся все итераторы после удаляемого элемента, в нашем примере — все итераторы после >i
. Конструкции вида >i++
, >++i
и т. д. невозможны, поскольку ни один из полученных итераторов не будет действительным.
Следовательно, с >vector
, >string
и >deque
нужно действовать иначе. Мы должны воспользоваться возвращаемым значением erase, которое содержит именно то, что нам требуется — действительный итератор, который указывает на элемент, следующий за удаленным. Иначе говоря, программа выглядит примерно так:
>for(ПослКонтейнер
> if (badValue(*i)) {
> logFile<<"Erasing "<<*i<<'\n';
> i=c.erase()); // Сохраняем действительный итератор i,
> } // для чего ему присваивается значение,
> else ++i; // возвращаемое функцией erase
>}
Такое решение превосходно работает, но только для стандартных последовательных контейнеров. По весьма сомнительным причинам (совет 5) функция >erase
для стандартных ассоциативных контейнеров возвращает >void
. В этом случае приходится использовать методику с постфиксным приращением итератора, переданного >erase
. Кстати говоря, подобные различия между последовательными и ассоциативными контейнерами — один из примеров того, почему контейнерно-независимый код обычно считается нежелательным (совет 2).
Какое из этих решений лучше подойдет для контейнера >list
? Оказывается, в отношении перебора и удаления >list
может интерпретироваться как >vector/string/deque
или как ассоциативный контейнер — годятся оба способа. Обычно выбирается первый вариант, поскольку >list
, как и >vector/string/deque
, принадлежит к числу последовательных контейнеров. С точки зрения опытного программиста STL программа, в которой перебор и удаление из >list
производятся по правилам ассоциативных контейнеров, выглядит странно.
Подводя итог всему, о чем рассказывалось в этом совете, мы приходим к следующим заключениям.
Удаление всех объектов с заданным значением:
• контейнеры >vector
, >string
и >deque
: используйте идиому >erase/remove
;
• контейнер >list
: используйте >list::remove
;
• стандартный ассоциативный контейнер: используйте функцию >erase
.
Удаление всех объектов, соответствующих заданному предикату:
• контейнер >vector
, >string
и >deque
: используйте идиому >erase/remove_if
;
• контейнер >list
: используйте >list::remove_if
;
• стандартный ассоциативный контейнер: используйте >remove_copy_if/swap
или напишите цикл перебора элементов контейнера, но не забудьте о постфиксном приращении итератора, передаваемого при вызове >erase
.
Дополнительные операции в цикле (кроме удаления объектов):
• стандартный последовательный контейнер: напишите цикл перебора элементов, но не забывайте обновлять итератор значением, возвращаемым >erase
при каждом вызове;
• стандартный ассоциативный контейнер: напишите цикл перебора элементов с постфиксным приращением итератора, передаваемого при вызове >erase
.
Как видите, эффективное удаление элементов контейнера не сводится к простому вызову >erase
. Правильный подход зависит от того, по какому принципу отбираются удаляемые элементы, в каком контейнере они хранятся и какие дополнительные операции требуется выполнить при удалении. Действуйте осторожно и следуйте рекомендациям данного совета, и все будет нормально. Невнимательность обернется неэффективной работой или непредсказуемым поведением программы.
Эффективный и современный С++Освоение С++11 и С++14 — это больше, чем просто ознакомление с вводимыми этими стандартами возможностями (например, объявлениями типов auto, семантикой перемещения, лямбда-выражениями или поддержкой многопоточности). Вопрос в том, как использовать их эффективно, чтобы создаваемые программы были корректны, эффективны и переносимы, а также чтобы их легко можно было сопровождать. Именно этим вопросам и посвящена данная книга, описывающая создание по-настоящему хорошего программного обеспечения с использованием C++11 и С++14 — т.е.
Когда приходится инкапсулировать, то иногда лучше меньше, чем большеЯ начну со следующего утверждения: Если вы пишете функцию, которая может быть выполнена или как метод класса, или быть внешней по отношению к классу, Вы должны предпочесть ее реализацию без использования метода. Такое решение увеличивает инкапсуляцию класса. Когда Вы думаете об использовании инкапсуляции, Вы должны думать том, чтобы не использовать методы.Удивлены? Читайте дальше.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
Сейчас во многих школах, институтах и других учебных заведениях можно встретить компьютеры старого парка, уже отслужившие свое как морально, так и физически. На таких компьютерах можно изучать разве что Dos, что далеко от реалий сегодняшнего дня. К тому же у большинства, как правило, жесткий диск уже в нерабочем состоянии. Но и выбросить жалко, а новых никто не дает. Различные спонсоры, меценаты, бывает, подарят компьютер (один) и радуются, как дети. Спасибо, конечно, большое, но проблемы, как вы понимаете, этот компьютер в общем не решает, даже наоборот, усугубляет, работать на старых уже как-то не хочется, теперь просто есть с чем сравнивать.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.
Что общего между самыми востребованными профессиями и стремительным увеличением количества информации в мире? Ответ: язык структурированных запросов (SQL). SQL — рабочая лошадка среди языков программирования, основа основ для современного анализа и управления данными. Книга «SQL: быстрое погружение» идеальна для всех, кто ищет новые перспективы карьерного роста; для разработчиков, которые хотят расширить свои навыки и знания в программировании; для любого человека, даже без опыта, кто хочет воспользоваться возможностями будущего, в котором будут править данные.
Даже плохой программный код может работать. Однако если код не является «чистым», это всегда будет мешать развитию проекта и компании-разработчика, отнимая значительные ресурсы на его поддержку и «укрощение». Эта книга посвящена хорошему программированию. Она полна реальных примеров кода. Мы будем рассматривать код с различных направлений: сверху вниз, снизу вверх и даже изнутри. Прочитав книгу, вы узнаете много нового о коде. Более того, вы научитесь отличать хороший код от плохого. Вы узнаете, как писать хороший код и как преобразовать плохой код в хороший. Книга состоит из трех частей.
Книга "Изучаем Python" - это ускоренный курс, который позволит вам сэкономить время и сразу начать писать работоспособные программы (игры, визуализации данных, веб-приложения и многое другое). Хотите стать программистом? В первой части книги вам предстоит узнать о базовых принципах программирования, познакомиться со списками, словарями, классами и циклами, вы научитесь создавать программы и тестировать код. Во второй части книги вы начнете использовать знания на практике, работая над тремя крупными проектами: создадите собственную "стрелялку" с нарастающей сложностью уровней, займетесь работой с большими наборами данных и освоите их визуализацию, и, наконец, создадите полноценное веб-приложение на базе Django, гарантирующее конфиденциальность пользовательской информации. Если вы решились разобраться в том что такое программирование, не нужно ждать.
Алгоритмы - это всего лишь пошаговые алгоритмы решения задач, и большинство таких задач уже были кем-то решены, протестированы и проверены. Можно, конечно, погрузится в глубокую философию гениального Кнута, изучить многостраничные фолианты с доказательствами и обоснованиями, но хотите ли вы тратить на это свое время? Откройте великолепно иллюстрированную книгу и вы сразу поймете, что алгоритмы - это просто. А грокать алгоритмы - это веселое и увлекательное занятие.