Скотт Мейерс - Эффективное использование 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 - читать книгу онлайн бесплатно, автор Скотт Мейерс
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать
Конечно мы не можем использовать n для обозначения позиции вставки поскольку - фото 8

Конечно, мы не можем использовать n для обозначения позиции вставки, поскольку это не iterator. Вместо этого необходимо использовать i. Как упоминалось выше, когда n указывает на элемент 3, i (то есть r. base()) указывает на элемент 4. Именно на эту позицию должен указывать итератор i, чтобы вставленный элемент оказался в той позиции, в которой он бы находился, если бы для вставки можно было использовать итератор r.

Заключение:

• чтобы эмулировать вставку в позицию, заданную итератором ri типа reverse_ iterator, выполните вставку в позицию r.base(). По отношению к операции вставки ri и r.base() эквивалентны, но r.base() в действительности представляет собой iterator, соответствующий ri.

Рассмотрим операцию удаления элемента. Вернемся к взаимосвязи между ri и исходным вектором (по состоянию на момент, предшествующий вставке значения 99):

Для удаления элемента на который указывает итератор r нельзя просто - фото 9

Для удаления элемента, на который указывает итератор r, нельзя просто использовать , поскольку этот итератор ссылается на другой элемент. Вместо этого нужно удалить элемент, предшествующий i .

Заключение:

• чтобы эмулировать удаление в позиции, заданной итератором ri типа reverse_ iterator, выполните удаление в позиции, предшествующей ri .base(). По отношению к операции удаления ri и ri .base() не эквивалентны, a ri .base() не является объектом iterator, соответствующим ri.

Однако к коду стоит присмотреться повнимательнее, поскольку вас ждет сюрприз:

vector v;

… // См. ранее. В вектор v заносятся // числа 1-5

vector::reverse_iterator ri = // Установить ri на элемент 3

find(v.rbegin(),v.rend(),3);

v.erase(--ri .base());// Попытка стирания в позиции.

// предшествующей ri-base():

// для вектора обычно

// не компилируется

Решение выглядит вполне нормально. Выражение --ri.base()правильно определяет элемент, предшествующий удаляемому. Более того, приведенный фрагмент будет нормально работать для всех стандартных контейнеров, за исключением vector и string. Наверное, он бы мог работать и для этих контейнеров, но во многих реализациях vector и string он не будет компилироваться. В таких реализациях типы iterator (и const_iterator) реализованы в виде встроенных указателей, поэтому результатом вызова i.base()является указатель. В соответствии с требованиями как С, так и С++ указатели, возвращаемые функциями, не могут модифицироваться, поэтому на таких платформах STL выражения типа --i.base()не компилируются. Чтобы удалить элемент в позиции, заданной итератором reverse_iterator , и при этом сохранить переносимость, необходимо избегать модификации возвращаемого значения base. Впрочем, это несложно. Если мы не можем уменьшить результат вызова base, значит, нужно увеличить reverse_iterator и после этого вызвать base!

//См. ранее

v.erase((++ri).base()); // Удалить элемент, на который указывает ri;

// команда всегда компилируется

Такая методика работает во всех стандартных контейнерах и потому считается предпочтительным способом удаления элементов, определяемых итератором reverse_iterator.

Вероятно, вы уже поняли: говорить о том, что функция base класса reverse_ iterator возвращает «соответствующий» iterator, не совсем правильно. В отношении вставки это действительно так, а в отношении удаления — нет. При преобразовании reverse_iterator в iterator важно знать, какие операции будут выполняться с полученным объектом iterator. Только в этом случае вы сможете определить, подойдет ли он для ваших целей.

Совет 29. Рассмотрите возможность использования istreambuf_iterator при посимвольном вводе

Предположим, вы хотите скопировать текстовый файл в объект string. На первый взгляд следующее решение выглядит вполне разумно:

ifstream inputFile("interestringData.txt");

string fileData(istream_iterator(inputFile)), // Прочитать inputFile istream iterator0);// в fileData

Но вскоре выясняется, что приведенный синтаксис не копирует в строку пропуски (whitespace), входящие в файл. Это объясняется тем, что isream_iterator производит непосредственное чтение функциями operator<<, а эти функции по умолчанию не читают пропуски.

Чтобы сохранить пропуски, входящие в файл, достаточно включить режим чтения пропусков сбросом флага skipws для входного потока:

ifstream inputFile("interestingData.txt"):

inputFle.unset(ios::skipws);// Включить режим

// чтения пропусков

// в inputFile

string fileData(istream_iterator(inputFile)), // Прочитать inputFile istream_iterator0);// в fileData.

Теперь все символы InputFile копируются в fileData.

Кроме того, может выясниться, что копирование происходит не так быстро, как вам хотелось бы. Функции operator<<, от которых зависит работа stream_iterator, производят форматный ввод, а это означает, что каждый вызов сопровождается многочисленными служебными операциями. Они должны создать и уничтожить объекты sentry (специальные объекты потоков ввода-вывода, выполняющие начальные и завершающие операции при каждом вызове operator<<); они должны проверить состояние флагов, влияющих на их работу (таких, как skpws); они должны выполнить доскональную проверку ошибок чтения, а в случае обнаружения каких-либо проблем — проанализировать маску исключений потока и определить, нужно ли инициировать исключение. Все перечисленные операции действительно важны при форматном вводе, но если ваши потребности ограничиваются чтением следующего символа из входного потока, без них можно обойтись.

Более эффективное решение основано на использовании неприметного итератора istreambuf_iterator. Итераторы istreambuf_iterator работают аналогично istream_iterator, но если объекты istream_iterator читают отдельные символы из входного потока оператором <<, то объекты streambuf_iterator обращаются прямо к буферу потока и непосредственно читают следующий символ (выражаясь точнее, объект streambuf_iterator читает следующий символ из входного потока s вызовом s.rdbuf ()->sgetc()).

Перейти на использование istreambuf_iiterator при чтении файла так просто, что даже программист Visual Basic сделает это со второй попытки:

ifstream inputFile("interestingData.txt");

string fileData(istreambuf_iterator(inputFile)). istreambuf_iterator0);

На этот раз сбрасывать флаг skpws не нужно, итераторы streambuf_iterator никогда не пропускают символы при вводе и просто возвращают следующий символ из буфера.

По сравнению с istream_iterator это происходит относительно быстро. В проведенных мною простейших тестах выигрыш по скорости достигал 40%, хотя в вашем случае цифры могут быть другими. Не удивляйтесь, если быстродействие будет расти со временем; итераторы istreambuf_iterator населяют один из заброшенных уголков STL, и авторы реализаций еще недостаточно позаботились об их оптимизации. Например, в моих примитивных тестах итераторы istreambuf_iterator одной из реализаций работали всего на 5% быстрее, чем istream_iterator. В таких реализациях остается широкий простор для оптимизации i streambuf_iterator.

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

Интервал:

Закладка:

Сделать


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

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




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


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


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

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