Эффективное использование STL - [54]
> // когда приведенное выше сравнение не работает
Подобные проблемы возникают не только при сравнении, но и вообще при смешанном использовании >iterator
и >const_iterator
(или >reverse_iterator
и >const_reverse_iterator
) в одном выражении, например, при попытке вычесть один итератор произвольного доступа из другого:
>if (i-ci>=3)… // Если i находится минимум в трех позициях после ci…
ваш (правильный) код будет несправедливо отвергнут компилятором, если итераторы относятся к разным типам. Обходное решение остается прежним (перестановка >i
и >ci
), но в этом случае приходится учитывать, что >i-ci
не заменяется на >ci-i
:
>if (c+3<=i)… // Обходное решение на случай, если
> // предыдущая команда не компилируется
Простейшая страховка от подобных проблем заключается в том, чтобы свести к минимуму использование разнотипных итераторов, а это в свою очередь подсказывает, что вместо >const_iterator
следует использовать >iterator
. На первый взгляд отказ от >const_iterator
только для предотвращения потенциальных недостатков реализации (к тому же имеющих обходное решение) выглядит неоправданным, но с учетом особого статуса >iterator
в некоторых функциях контейнеров мы неизбежно приходим к выводу, что итераторы >const_iterator
менее практичны, а хлопоты с ними иногда просто не оправдывают затраченных усилий.
Совет 27. Используйте distance и advance для преобразования const_iterator в iterator
Как было сказано в совете 26, некоторые функции контейнеров, вызываемые с параметрами-итераторами, ограничиваются типом >iterator
; >const_iterator
им не подходит. Что же делать, если имеется >const_iterator
и вы хотите вставить новый элемент в позицию контейнера, обозначенную этим итератором? >Const_iterator
необходимо каким-то образом преобразовать в >iterator
, и вы >должны
принять в этом активное участие, поскольку, как было показано в совете 26, автоматического преобразования >const_iterator
в iterator не существует.
Я знаю, о чем вы думаете. «Если ничего не помогает, берем кувалду», не так ли? В мире C++ это может означать лишь одно: преобразование типа. Стыдитесь. И где вы набрались таких мыслей?
Давайте разберемся с вредным заблуждением относительно преобразования типа. Посмотрим, что происходит при преобразовании >const_iterator
в >iterator
:
>typedef deque
>typedef IntDeque::iterator Iter;
>typedef IntDeque::const_iterator ConstIter;
>ConstIter ci; // ci - const iterator
>Iter i(ci); // Ошибка! He существует автоматического
> // преобразования const_iterator
> // в iterator
>Iter i(const_cast
> // в iterator невозможно!
В приведенном примере используется контейнер >deque
, но аналогичный результат будет получен и для >list, set, muliset, mulimap
и хэшированных контейнеров, упоминавшихся в совете 25. Возможно, строка с преобразованием будет откомпилирована >для
vector и >string
, но это особые случаи, которые будут рассмотрены ниже.
Почему же для этих типов контейнеров преобразование не компилируется? Потому что >iterator
и >const_iterator
относятся к разным классам, и сходства между ними не больше, чем между >string
и >complex
. Попытка преобразования одного типа в другой абсолютно бессмысленна, поэтому вызов >const_cast
будет отвергнут. Попытки использования >static_cast
, >reintepreter_cast
и преобразования в стиле C приведут к тому же результату.
Впрочем, некомпилируемое преобразование все же может откомпилироваться, если итераторы относятся к контейнеру >vector
или >string
. Это объясняется тем, что в реализациях данных контейнеров в качестве итераторов обычно используются указатели. В этих реализациях >vector
является определением типа для >T*, vector
— для >const T*
, >string::iterator
— для >char*
, а >string::const_iterator
— для >const char*
. В реализациях данных контейнеров преобразование >const_iterator
в >iterator
вызовом >const_cast
компилируется и даже правильно работает, поскольку оно преобразует >const T*
в >T*
. Впрочем, даже в этих реализациях >reverse_iterator
и >const_reverse_iterator
являются полноценными классами, поэтому >const_cast
не позволяет преобразовать >const_reverse_iterator
в >reverse_iterator
. Кроме того, как объясняется в совете 50, даже реализации, в которых итераторы контейнеров >vector
и >string
представлены указателями, могут использовать это представление лишь при компиляции окончательной (release) версии. Все перечисленные факторы приводят к мысли, что преобразование >const
-итераторов в итераторы не рекомендуется и для контейнеров >vector
и >string
, поскольку переносимость такого решения будет сомнительной.
Если у вас имеется доступ к контейнеру, от которого был взят >const_iterator
, существует безопасный, переносимый способ получения соответствующего типа >iterator
без нарушения системы типов. Ниже приведена основная часть этого решения (возможно, перед компиляцией потребуется внести небольшие изменения):
>typedef deque
>typedef IntDeque::iterator Iter;
Эффективный и современный С++Освоение С++11 и С++14 — это больше, чем просто ознакомление с вводимыми этими стандартами возможностями (например, объявлениями типов auto, семантикой перемещения, лямбда-выражениями или поддержкой многопоточности). Вопрос в том, как использовать их эффективно, чтобы создаваемые программы были корректны, эффективны и переносимы, а также чтобы их легко можно было сопровождать. Именно этим вопросам и посвящена данная книга, описывающая создание по-настоящему хорошего программного обеспечения с использованием C++11 и С++14 — т.е.
Когда приходится инкапсулировать, то иногда лучше меньше, чем большеЯ начну со следующего утверждения: Если вы пишете функцию, которая может быть выполнена или как метод класса, или быть внешней по отношению к классу, Вы должны предпочесть ее реализацию без использования метода. Такое решение увеличивает инкапсуляцию класса. Когда Вы думаете об использовании инкапсуляции, Вы должны думать том, чтобы не использовать методы.Удивлены? Читайте дальше.
Разработчику часто требуется много сторонних инструментов, чтобы создавать и поддерживать проект. Система Git — один из таких инструментов и используется для контроля промежуточных версий вашего приложения, позволяя вам исправлять ошибки, откатывать к старой версии, разрабатывать проект в команде и сливать его потом. В книге вы узнаете об основах работы с Git: установка, ключевые команды, gitHub и многое другое.В книге рассматриваются следующие темы:основы Git;ветвление в Git;Git на сервере;распределённый Git;GitHub;инструменты Git;настройка Git;Git и другие системы контроля версий.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.
Что общего между самыми востребованными профессиями и стремительным увеличением количества информации в мире? Ответ: язык структурированных запросов (SQL). SQL — рабочая лошадка среди языков программирования, основа основ для современного анализа и управления данными. Книга «SQL: быстрое погружение» идеальна для всех, кто ищет новые перспективы карьерного роста; для разработчиков, которые хотят расширить свои навыки и знания в программировании; для любого человека, даже без опыта, кто хочет воспользоваться возможностями будущего, в котором будут править данные.
Даже плохой программный код может работать. Однако если код не является «чистым», это всегда будет мешать развитию проекта и компании-разработчика, отнимая значительные ресурсы на его поддержку и «укрощение». Эта книга посвящена хорошему программированию. Она полна реальных примеров кода. Мы будем рассматривать код с различных направлений: сверху вниз, снизу вверх и даже изнутри. Прочитав книгу, вы узнаете много нового о коде. Более того, вы научитесь отличать хороший код от плохого. Вы узнаете, как писать хороший код и как преобразовать плохой код в хороший. Книга состоит из трех частей.
Книга "Изучаем Python" - это ускоренный курс, который позволит вам сэкономить время и сразу начать писать работоспособные программы (игры, визуализации данных, веб-приложения и многое другое). Хотите стать программистом? В первой части книги вам предстоит узнать о базовых принципах программирования, познакомиться со списками, словарями, классами и циклами, вы научитесь создавать программы и тестировать код. Во второй части книги вы начнете использовать знания на практике, работая над тремя крупными проектами: создадите собственную "стрелялку" с нарастающей сложностью уровней, займетесь работой с большими наборами данных и освоите их визуализацию, и, наконец, создадите полноценное веб-приложение на базе Django, гарантирующее конфиденциальность пользовательской информации. Если вы решились разобраться в том что такое программирование, не нужно ждать.
Алгоритмы - это всего лишь пошаговые алгоритмы решения задач, и большинство таких задач уже были кем-то решены, протестированы и проверены. Можно, конечно, погрузится в глубокую философию гениального Кнута, изучить многостраничные фолианты с доказательствами и обоснованиями, но хотите ли вы тратить на это свое время? Откройте великолепно иллюстрированную книгу и вы сразу поймете, что алгоритмы - это просто. А грокать алгоритмы - это веселое и увлекательное занятие.