Книги
чёрным по белому
Главное меню
Главная О нас Добавить материал Поиск по сайту Карта книг Карта сайта
Книги
Археология Архитектура Бизнес Биология Ветеринария Военная промышленность География Геология Гороскоп Дизайн Журналы Инженерия Информационные ресурсы Искусство История Компьютерная литература Криптология Кулинария Культура Лингвистика Математика Медицина Менеджмент Металлургия Минералогия Музыка Научная литература Нумизматика Образование Охота Педагогика Политика Промышленные производства Психология Путеводители Религия Рыбалка Садоводство Саморазвитие Семиотика Социология Спорт Столярное дело Строительство Техника Туризм Фантастика Физика Футурология Химия Художественная литература Экология Экономика Электроника Энергетика Этика Юриспруденция
Новые книги
Цуканов Б.И. "Время в психике человека" (Медицина)

Суворов С. "Танк Т-64. Первенец танков 2-го поколения " (Военная промышленность)

Нестеров В.А. "Основы проэктирования ракет класса воздух- воздух и авиационных катапульных установок для них" (Военная промышленность)

Фогль Б. "101 вопрос, который задала бы ваша кошка своему ветеринару если бы умела говорить" (Ветеринария)

Яблоков Н.П. "Криминалистика" (Юриспруденция)
Реклама

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

Мейерс С. Эффективное использование STL. Библиотека программиста — Спб.: Питер , 2002. — 224 c.
ISBN 5-94723-382-7
Скачать (прямая ссылка): effektivnoeispolzovaniestlbibliote2002.djvu
Предыдущая << 1 .. 53 54 55 56 57 58 < 59 > 60 61 62 63 64 65 .. 114 >> Следующая

Стыдитесь. И где вы набрались таких мыслей?
Давайте разберемся с вредным заблуждением относительно преобразования
типа. Посмотрим, что происходит при преобразовании consti terator в
iterator:
typedef deque<int> IntDeque: // Вспомогательные определения типов
typedef IntDeque::iterator Iter;
typedef IntDeque::const_iterator Constlter;
Constlter ci
// ci - const iterator
Совет 27 115
Iter i(ci); // Ошибка! He существует автоматического
// преобразования const_iterator // в iterator
Iter i(const_cast<Iter>(ci)): // Ошибка! Преобразование
const_iterator
// в iterator невозможно!
В приведенном примере используется контейнер deque, но аналогичный
результат будет получен и для 1 ist, set, multiset, multimap и
хэшированных контейнеров, упоминавшихся в совете 25. Возможно, строка с
преобразованием будет откомпилирована для vector и string, но это особые
случаи, которые будут рассмотрены ниже.
Почему же для этих типов контейнеров преобразование не компилируется?
Потому что iterator и const_iterator относятся к разным классам, и
сходства между ними не больше, чем между string и complex<doublе>.
Попытка преобразования одного типа в другой абсолютно бессмысленна,
поэтому вызов const_cast будет отвергнут. Попытки использования
static_cast, reinterpreter cast и преобразования в стиле С приведут к
тому же результату.
Впрочем, некомпилируемое преобразование все же может откомпилироваться,
если итераторы относятся к контейнеру vector или stri ng. Это объясняется
тем, что в реализациях данных контейнеров в качестве итераторов обычно
используются указатели. В этих реализациях vector<T>:: iterator является
определением типа для Т* vector<T>:: const_iterator - для const Т*,
string:: iterator - для char* a stri ng:: const i terator - для const
char*. В реализациях данных контейнеров преобразование const_iterator в
iterator вызовом const_cast компилируется и даже правильно работает,
поскольку оно преобразует const Т* в Т*. Впрочем, даже в этих реализациях
reverse i terator и const_reverse_i terator являются полноценными
классами, поэтому const cast не позволяет преобразовать const_reverse_i
terator в reverse_i terator. Кроме того, как объясняется в совете 50,
даже реализации, в которых итераторы контейнеров vector и stri ng
представлены указателями, могут использовать это представление лишь при
компиляции окончательной (release) версии. Все перечисленные факторы
приводят к мысли, что преобразование const-итераторов в итераторы не
рекомендуется и для контейнеров vector и string, поскольку переносимость
такого решения будет сомнительной.
Если у вас имеется доступ к контейнеру, от которого был взят const_i
terator, существует безопасный, переносимый способ получения
соответствующего типа iterator без нарушения системы типов. Ниже
приведена основная часть этого решения (возможно, перед компиляцией
потребуется внести небольшие изменения):
typedef deque<int> IntDeque: //См. ранее
typedef IntDeque::iterator Iter:
typedef IntDeque::const_iterator Constlter:
IntDeque d:
Constlter ci:
// Присвоить ci ссылку на d Iter i(d.beginO): // Инициализировать i
значением d.beginO
advanced .distanced,ci));
// Переместить i в позицию ci
116 Глава 4 • Итераторы
Решение выглядит настолько простым и прямолинейным, что это невольно
вызывает подозрения. Чтобы получить iterator, указывающий на тот же
элемент контейнера, что и const_iterator, мы создаем новый iterator в
начале контейнера и перемещаем его вперед до тех пор, пока он не удалится
на то же расстояние, что и const_iterator! Задачу упрощают шаблоны
функций advance и di stance, объявленные в <iterator>. Distance
возвращает расстояние между двумя итераторами в одном контейнере, a
advance перемещает итератор на заданное расстояние. Когда итераторы i и
ci относятся к одному контейнеру, выражение advance(i, di stance(i, ci))
переводит их в одну позицию контейнера.
Все хорошо, если бы этот вариант компилировался... но этого не
происходит. Чтобы понять причины, рассмотрим объявление di stance:
tempiate<typename InputIterator>
typename iterator_traits<InputIterator>::difference_type
distancednputlterator first.Inputlterator last);
He обращайте внимания на то, что тип возвращаемого значения состоит из 56
символов и содержит упоминания зависимых типов (таких как di
fference_type). Вместо этого проанализируем использование параметра-типа
Inputlterator:
tempiate<typename InputIterator>
typename iterator_traits<InputIterator>::difference_type
distancednputlterator first,Inputlterator last):
При вызове distance компилятор должен определить тип, представленный
Inputlterator, для чего он анализирует аргументы, переданные при вызове.
Еще раз посмотрим на вызов di stance в приведенном выше коде:
advance(i .distanced,ci)); // Переместить i в позицию ci
При вызове передаются два параметра, i и ci. Параметр i относится к типу
iter, который представляет собой определение типа для deque<int>::
Предыдущая << 1 .. 53 54 55 56 57 58 < 59 > 60 61 62 63 64 65 .. 114 >> Следующая